Actualiser api.php

This commit is contained in:
2026-06-30 16:25:54 +02:00
parent 4121a198ab
commit ed7c2454b4
+65 -32
View File
@@ -394,9 +394,8 @@ function fetchFromBlurayCom($ean) {
error_log("Blu-ray.com: 🔍 Recherche EAN $ean"); error_log("Blu-ray.com: 🔍 Recherche EAN $ean");
// Recherche simple par EAN // Recherche par EAN
$searchUrl = "https://www.blu-ray.com/movies/search.php?ean=" . urlencode($ean) . "&action=search"; $searchUrl = "https://www.blu-ray.com/movies/search.php?ean=" . urlencode($ean) . "&action=search";
$ch = curl_init($searchUrl); $ch = curl_init($searchUrl);
curl_setopt_array($ch, [ curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
@@ -422,7 +421,7 @@ function fetchFromBlurayCom($ean) {
return $empty; return $empty;
} }
// Extraire l'URL du film // Extraire l'URL du film - regex améliorée
if (!preg_match('/href="(https:\/\/www\.blu-ray\.com\/movies\/[^"]+\/(\d+)\/)"/i', $searchHtml, $matches)) { if (!preg_match('/href="(https:\/\/www\.blu-ray\.com\/movies\/[^"]+\/(\d+)\/)"/i', $searchHtml, $matches)) {
error_log("Blu-ray.com: ❌ Film non trouvé pour EAN $ean"); error_log("Blu-ray.com: ❌ Film non trouvé pour EAN $ean");
return $empty; return $empty;
@@ -432,6 +431,9 @@ function fetchFromBlurayCom($ean) {
$movieId = $matches[2]; $movieId = $matches[2];
error_log("Blu-ray.com: ✅ Film trouvé → $movieUrl"); error_log("Blu-ray.com: ✅ Film trouvé → $movieUrl");
// Délai avant la 2ème requête
sleep(2);
// Récupérer la page du film // Récupérer la page du film
$ch2 = curl_init($movieUrl); $ch2 = curl_init($movieUrl);
curl_setopt_array($ch2, [ curl_setopt_array($ch2, [
@@ -455,28 +457,34 @@ function fetchFromBlurayCom($ean) {
return $empty; return $empty;
} }
// Extraction des données // Extraction des données - regex améliorées
// Titre
if (preg_match('/<h1[^>]*>([^<]+)<\/h1>/i', $movieHtml, $m)) { if (preg_match('/<h1[^>]*>([^<]+)<\/h1>/i', $movieHtml, $m)) {
$rawTitle = trim(strip_tags($m[1])); $rawTitle = trim(strip_tags($m[1]));
$empty['title'] = trim(preg_replace('/\s*(Blu-ray|4K|3D|DVD|UHD).*$/i', '', $rawTitle)); $empty['title'] = trim(preg_replace('/\s*(Blu-ray|4K|3D|DVD|UHD).*$/i', '', $rawTitle));
} }
// Année
if (preg_match('/href="[^"]*year=(\d{4})[^"]*"[^>]*>(\d{4})<\/a>/i', $movieHtml, $m)) { if (preg_match('/href="[^"]*year=(\d{4})[^"]*"[^>]*>(\d{4})<\/a>/i', $movieHtml, $m)) {
$empty['year'] = $m[1]; $empty['year'] = $m[1];
} }
// Studio/Éditeur
if (preg_match('/href="[^"]*studioid=\d+[^"]*"[^>]*>([^<]+)<\/a>/i', $movieHtml, $m)) { if (preg_match('/href="[^"]*studioid=\d+[^"]*"[^>]*>([^<]+)<\/a>/i', $movieHtml, $m)) {
$empty['publisher'] = trim($m[1]); $empty['publisher'] = trim($m[1]);
} }
// Durée
if (preg_match('/<span[^>]*id="runtime"[^>]*>(\d+)\s*min<\/span>/i', $movieHtml, $m)) { if (preg_match('/<span[^>]*id="runtime"[^>]*>(\d+)\s*min<\/span>/i', $movieHtml, $m)) {
$empty['length'] = $m[1] . ' min'; $empty['length'] = $m[1] . ' min';
} }
// Aspect ratio
if (preg_match('/Aspect[\s-]*ratio:\s*([\d\.]+:[\d\.]+)/i', $movieHtml, $m)) { if (preg_match('/Aspect[\s-]*ratio:\s*([\d\.]+:[\d\.]+)/i', $movieHtml, $m)) {
$empty['aspect_ratio'] = trim($m[1]); $empty['aspect_ratio'] = trim($m[1]);
} }
// Nombre de disques - plusieurs patterns
if (preg_match('/(\w+)-disc\s+set/i', $movieHtml, $m)) { if (preg_match('/(\w+)-disc\s+set/i', $movieHtml, $m)) {
$wordToNum = ['single' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5, 'six' => 6]; $wordToNum = ['single' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5, 'six' => 6];
$word = strtolower($m[1]); $word = strtolower($m[1]);
@@ -485,6 +493,7 @@ function fetchFromBlurayCom($ean) {
$empty['number_of_discs'] = (int)$m[1]; $empty['number_of_discs'] = (int)$m[1];
} }
// Format
if (strpos($movieUrl, '/4k/') !== false || stripos($movieHtml, '4K Ultra HD') !== false) { if (strpos($movieUrl, '/4k/') !== false || stripos($movieHtml, '4K Ultra HD') !== false) {
$empty['format'] = '4K Ultra HD'; $empty['format'] = '4K Ultra HD';
} elseif (strpos($movieUrl, '/3d/') !== false) { } elseif (strpos($movieUrl, '/3d/') !== false) {
@@ -493,36 +502,42 @@ function fetchFromBlurayCom($ean) {
$empty['format'] = 'Blu-ray'; $empty['format'] = 'Blu-ray';
} }
// Affiche HD // Affiche HD - plusieurs patterns
if (preg_match('/src="(https:\/\/images\.static-bluray\.com\/movies\/covers\/\d+_front\.jpg[^"]*)"/i', $movieHtml, $m)) { if (preg_match('/src="(https:\/\/images\.static-bluray\.com\/movies\/covers\/\d+_front\.jpg[^"]*)"/i', $movieHtml, $m)) {
$empty['poster'] = $m[1]; $empty['poster'] = $m[1];
} elseif (preg_match('/<img[^>]*class="coverfront"[^>]*src="([^"]+)"/i', $movieHtml, $m)) { } elseif (preg_match('/<img[^>]*class="coverfront"[^>]*src="([^"]+)"/i', $movieHtml, $m)) {
$empty['poster'] = $m[1]; $posterUrl = $m[1];
$posterUrl = preg_replace('/_large\.jpg/', '_front.jpg', $posterUrl);
$empty['poster'] = $posterUrl;
} }
// Synopsis, Réalisateur, Acteurs // Synopsis, Réalisateur, Acteurs
if (preg_match('/<div[^>]*id="movie_info"[^>]*>(.*?)<div[^>]*id="movie_review_intro"/is', $movieHtml, $infoBlock)) { if (preg_match('/<div[^>]*id="movie_info"[^>]*>(.*?)<div[^>]*id="movie_review_intro"/is', $movieHtml, $infoBlock)) {
$infoHtml = $infoBlock[1]; $infoHtml = $infoBlock[1];
// Synopsis
if (preg_match('/<\/center><br>\s*(.*?)<br><br><br>Director:/is', $infoHtml, $m)) { if (preg_match('/<\/center><br>\s*(.*?)<br><br><br>Director:/is', $infoHtml, $m)) {
$synopsis = trim(strip_tags($m[1])); $synopsis = trim(strip_tags($m[1]));
$synopsis = preg_replace('/\s+/', ' ', $synopsis); $synopsis = preg_replace('/\s+/', ' ', $synopsis);
$empty['description'] = $synopsis; $empty['description'] = $synopsis;
} }
// Réalisateur
if (preg_match('/Director:\s*<a[^>]*>([^<]+)<\/a>/i', $infoHtml, $m)) { if (preg_match('/Director:\s*<a[^>]*>([^<]+)<\/a>/i', $infoHtml, $m)) {
$empty['director'] = trim($m[1]); $empty['director'] = trim($m[1]);
} }
// Acteurs
if (preg_match('/Starring:\s*(.*?)(?:<br>|<\/div>)/is', $infoHtml, $m)) { if (preg_match('/Starring:\s*(.*?)(?:<br>|<\/div>)/is', $infoHtml, $m)) {
preg_match_all('/<a[^>]*>([^<]+)<\/a>/i', $m[1], $actorMatches); $actorsHtml = $m[1];
preg_match_all('/<a[^>]*>([^<]+)<\/a>/i', $actorsHtml, $actorMatches);
if (!empty($actorMatches[1])) { if (!empty($actorMatches[1])) {
$empty['actors'] = implode(', ', array_map('trim', array_slice($actorMatches[1], 0, 6))); $empty['actors'] = implode(', ', array_map('trim', array_slice($actorMatches[1], 0, 6)));
} }
} }
} }
error_log("Blu-ray.com: ✅ Données récupérées → " . $empty['title']); error_log("Blu-ray.com: ✅ Données récupérées pour EAN $ean" . $empty['title']);
return $empty; return $empty;
} }
@@ -534,6 +549,8 @@ function fetchFromMovieCovers($title, $year = '') {
'aspect_ratio' => '' 'aspect_ratio' => ''
]; ];
if (empty($title)) return $empty;
// Nettoyer le titre pour l'URL // Nettoyer le titre pour l'URL
$urlTitle = strtoupper(str_replace(' ', '+', $title)); $urlTitle = strtoupper(str_replace(' ', '+', $title));
$url = "https://moviecovers.com/film/titre_{$urlTitle}.html"; $url = "https://moviecovers.com/film/titre_{$urlTitle}.html";
@@ -546,13 +563,18 @@ function fetchFromMovieCovers($title, $year = '') {
$empty['title'] = trim($m[1]); $empty['title'] = trim($m[1]);
} }
// Extraire l'affiche // Extraire l'affiche - plusieurs patterns
if (preg_match('/<img[^>]*src="(https:\/\/moviecovers\.com\/DATA\/thumbs\/[^"]+)"[^>]*title="Recto/i', $html, $m)) { if (preg_match('/<img[^>]*src="(https:\/\/moviecovers\.com\/DATA\/thumbs\/[^"]+)"[^>]*title="Recto/i', $html, $m)) {
$empty['poster'] = $m[1]; $empty['poster'] = $m[1];
} elseif (preg_match('/<meta[^>]*property="og:image"[^>]*content="([^"]+)"/i', $html, $m)) { } elseif (preg_match('/<meta[^>]*property="og:image"[^>]*content="([^"]+)"/i', $html, $m)) {
$empty['poster'] = $m[1]; $empty['poster'] = $m[1];
} }
// Format haute qualité de l'affiche
if ($empty['poster']) {
$empty['poster'] = str_replace('/thumbs/', '/films-l/', $empty['poster']);
}
// Extraire le réalisateur // Extraire le réalisateur
if (preg_match('/R&eacute;alisateur<\/TH>\s*<TD[^>]*>.*?<a[^>]*>([^<]+)<\/a>/is', $html, $m)) { if (preg_match('/R&eacute;alisateur<\/TH>\s*<TD[^>]*>.*?<a[^>]*>([^<]+)<\/a>/is', $html, $m)) {
$empty['director'] = trim($m[1]); $empty['director'] = trim($m[1]);
@@ -578,11 +600,6 @@ function fetchFromMovieCovers($title, $year = '') {
$empty['description'] = html_entity_decode($m[1]); $empty['description'] = html_entity_decode($m[1]);
} }
// Format haute qualité de l'affiche
if ($empty['poster']) {
$empty['poster'] = str_replace('/thumbs/', '/films-l/', $empty['poster']);
}
return $empty; return $empty;
} }
@@ -725,8 +742,10 @@ case 'import_batch':
$data = json_decode(file_get_contents("php://input"), true); $data = json_decode(file_get_contents("php://input"), true);
$type = $data['type'] ?? ''; $type = $data['type'] ?? '';
$items = $data['items'] ?? []; $items = $data['items'] ?? [];
$pdo->beginTransaction(); $pdo->beginTransaction();
$imported = 0; $skipped = 0; $imported = 0; $skipped = 0;
try { try {
if ($type === 'videotheque') { if ($type === 'videotheque') {
$stmt = $pdo->prepare("INSERT INTO videotheque (id, title, year, format, poster, ean_isbn13, description, length, number_of_discs, aspect_ratio, actors, publisher, director) $stmt = $pdo->prepare("INSERT INTO videotheque (id, title, year, format, poster, ean_isbn13, description, length, number_of_discs, aspect_ratio, actors, publisher, director)
@@ -743,22 +762,32 @@ case 'import_batch':
director=IF(VALUES(director)!='', VALUES(director), director)"); director=IF(VALUES(director)!='', VALUES(director), director)");
foreach ($items as $item) { foreach ($items as $item) {
$csvTitle = trim($item['title'] ?? '');
$ean = preg_replace('/[^0-9]/', '', (string)($item['ean'] ?? '')); $ean = preg_replace('/[^0-9]/', '', (string)($item['ean'] ?? ''));
$csvTitle = trim($item['title'] ?? '');
if (empty($csvTitle)) { if (strlen($ean) < 8 && empty($csvTitle)) {
$skipped++;
continue;
}
// 1. Essayer Blu-ray.com (avec throttling)
$blurayData = !empty($ean) ? fetchFromBlurayCom($ean) : [];
// 2. Si Blu-ray.com échoue, essayer MovieCovers avec le titre CSV
if (empty($blurayData['title']) && !empty($csvTitle)) {
error_log("Import: 🔄 Blu-ray.com échoué, essai MovieCovers pour '$csvTitle'");
$blurayData = array_merge($blurayData, fetchFromMovieCovers($csvTitle, ''));
}
// 3. Utiliser le titre trouvé ou le titre CSV
$title = !empty($blurayData['title']) ? $blurayData['title'] : $csvTitle;
if (empty($title)) {
error_log("Import: ❌ Pas de titre pour EAN $ean - ignoré"); error_log("Import: ❌ Pas de titre pour EAN $ean - ignoré");
$skipped++; $skipped++;
continue; continue;
} }
error_log("Import: 🎬 Traitement de '$csvTitle' (EAN: $ean)");
// 1. Essayer Blu-ray.com (peut échouer sans bloquer)
$blurayData = !empty($ean) ? fetchFromBlurayCom($ean) : [];
// 2. Utiliser le titre du CSV comme base
$title = $csvTitle;
$year = $blurayData['year'] ?? ''; $year = $blurayData['year'] ?? '';
$format = $blurayData['format'] ?: detectFormat($title); $format = $blurayData['format'] ?: detectFormat($title);
$publisher = $blurayData['publisher'] ?? ''; $publisher = $blurayData['publisher'] ?? '';
@@ -770,11 +799,11 @@ case 'import_batch':
$director = $blurayData['director'] ?? ''; $director = $blurayData['director'] ?? '';
$actors = $blurayData['actors'] ?? ''; $actors = $blurayData['actors'] ?? '';
// 3. COMPLÉTER avec TMDB (toujours appelé pour garantir les données) // 4. Fallback TMDB si données manquantes
error_log("Import: 🔄 Appel TMDB pour '$title'"); if (empty($poster) || empty($director) || empty($actors) || empty($desc)) {
error_log("Import: 🔄 Fallback TMDB pour '$title'");
$tmdb = fetchTmdbPosterAndSynopsis($title, $year, $pdo); $tmdb = fetchTmdbPosterAndSynopsis($title, $year, $pdo);
// TMDB complète ce qui manque
if (empty($poster) || $poster === 'assets/img/default_physical_media.jpg') { if (empty($poster) || $poster === 'assets/img/default_physical_media.jpg') {
$poster = $tmdb['poster']; $poster = $tmdb['poster'];
} }
@@ -783,14 +812,16 @@ case 'import_batch':
if (empty($desc)) $desc = $tmdb['description'] ?? ''; if (empty($desc)) $desc = $tmdb['description'] ?? '';
if (empty($length) && !empty($tmdb['length'])) $length = $tmdb['length']; if (empty($length) && !empty($tmdb['length'])) $length = $tmdb['length'];
if (empty($year) && !empty($tmdb['year'])) $year = $tmdb['year']; if (empty($year) && !empty($tmdb['year'])) $year = $tmdb['year'];
}
$id = makeStableId('videotheque', $title, $year); $id = makeStableId('videotheque', $title, $year);
$stmt->execute([$id, $title, $year, $format, $poster, $ean, $desc, $length, $discs, $aspect, $actors, $publisher, $director]); $stmt->execute([$id, $title, $year, $format, $poster, $ean, $desc, $length, $discs, $aspect, $actors, $publisher, $director]);
$imported++; $imported++;
error_log("Import: ✅ Importé '$title' (ID: $id)"); error_log("Import: ✅ Importé '$title' ($ean) - Disques: $discs, Format: $format");
} }
} else { // ── IMPORTATION CRITIQUES ── } else {
// Import critiques (inchangé)
$stmtCritiques = $pdo->prepare("INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) $stmtCritiques = $pdo->prepare("INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director),
@@ -802,13 +833,14 @@ case 'import_batch':
$year = $rowData['Year'] ?? $rowData['year'] ?? ''; $year = $rowData['Year'] ?? $rowData['year'] ?? '';
$id = makeStableId('critique', $title, $year); $id = makeStableId('critique', $title, $year);
$ratingRaw = $rowData['Rating'] ?? $rowData['rating'] ?? ''; $ratingRaw = $rowData['Rating'] ?? $rowData['rating'] ?? '';
$rating = ($ratingRaw !== '' && $ratingRaw !== null) ? (float)$ratingRaw : null; $rating = ($ratingRaw !== '' && $ratingRaw !== null) ? (float)$ratingRaw : null;
$review = $rowData['Review'] ?? $rowData['review'] ?? ''; $review = $rowData['Review'] ?? $rowData['review'] ?? '';
$director = ''; $poster = 'assets/img/default_physical_media.jpg'; $streaming = 'Support physique / Cinéma';
// ── CORRECTION ICI : Utilisation de la bonne fonction TMDB ── $director = '';
$poster = 'assets/img/default_physical_media.jpg';
$streaming = 'Support physique / Cinéma';
$tmdbData = fetchTmdbPosterAndSynopsis($title, $year, $pdo); $tmdbData = fetchTmdbPosterAndSynopsis($title, $year, $pdo);
if ($tmdbData) { if ($tmdbData) {
if (!empty($tmdbData['director'])) $director = $tmdbData['director']; if (!empty($tmdbData['director'])) $director = $tmdbData['director'];
@@ -820,10 +852,11 @@ case 'import_batch':
$imported++; $imported++;
} }
} }
$pdo->commit(); $pdo->commit();
echo json_encode(["success" => true, "imported" => $imported, "skipped" => $skipped]); echo json_encode(["success" => true, "imported" => $imported, "skipped" => $skipped]);
} catch (Throwable $e) { // ── CORRECTION ICI : Throwable capture les Crash Fatals PHP ── } catch (Throwable $e) {
$pdo->rollBack(); $pdo->rollBack();
error_log("import_batch error: " . $e->getMessage()); error_log("import_batch error: " . $e->getMessage());
http_response_code(500); http_response_code(500);