Actualiser api.php

This commit is contained in:
2026-07-24 11:18:48 +02:00
parent acf774da3d
commit 6051a91cab
+65 -136
View File
@@ -97,10 +97,11 @@ function removeAccentsForUrl($str) {
return $str;
}
// CORRECTION : Ajout du modificateur /u pour une gestion parfaite de l'UTF-8 et des accents
// CORRECTION : Nettoyage générique universel (UTF-8, parenthèses, formats et suffixes descriptifs)
function cleanTitle($title) {
// 1. Supprime tout contenu entre parenthèses ou crochets
$clean = preg_replace('/\s*[\[\(].*?[\]\)]\s*/u', '', $title);
$clean = preg_replace('/\s*-\s*(édition|Edition|Collector|Simple|Spéciale|Digibook|Ultimate|Intégrale|Combo|SteelBook|Boîtier).*$/iu', '', $clean);
// 2. Supprime les éditions physiques et formats courants en fin de chaîne
$clean = preg_replace('/(blu-ray|bluray|dvd|4k|ultra hd|combo|vhs|bdrip).*$/iu', '', $clean);
return trim(preg_replace('/\s{2,}/u', ' ', $clean));
}
@@ -232,109 +233,6 @@ function fetchFromFnac($ean) {
return $empty;
}
function fetchFromBlurayComByTitle($title) {
static $lastRequest = 0;
$empty = emptyPhysicalResult();
if (empty($title)) return $empty;
$now = microtime(true);
if ($lastRequest > 0 && ($now - $lastRequest) < 3) usleep((int)((3 - ($now - $lastRequest)) * 1000000));
$lastRequest = microtime(true);
$cleanTitle = cleanTitle($title);
$searchUrl = "https://www.blu-ray.com/movies/search.php?keyword=" . urlencode($cleanTitle) . "&action=search";
$ch = curl_init($searchUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
CURLOPT_HTTPHEADER => ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language: fr-FR,fr;q=0.9', 'Referer: https://www.blu-ray.com/']
]);
$searchHtml = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$searchHtml || $httpCode !== 200 || !preg_match('/href="(https:\/\/www\.blu-ray\.com\/movies\/[^"]+\/(\d+)\/)"/i', $searchHtml, $matches)) return $empty;
$movieUrl = $matches[1];
sleep(2);
$ch2 = curl_init($movieUrl);
curl_setopt_array($ch2, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_HTTPHEADER => ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Referer: https://www.blu-ray.com/']
]);
$movieHtml = curl_exec($ch2);
curl_close($ch2);
if (!$movieHtml) return $empty;
if (preg_match('/<h3[^>]*>([^<]+)<\/h3>\s*(?:&nbsp;)?\((\d{4})\)/i', $movieHtml, $m)) $empty['year'] = $m[2];
if (preg_match('/href="[^"]*studioid=\d+[^"]*"[^>]*>([^<]+)<\/a>/i', $movieHtml, $m)) $empty['publisher'] = trim($m[1]);
if (preg_match('/(\d+)\s*min<\/span>/i', $movieHtml, $m)) $empty['length'] = $m[1] . ' min';
if (preg_match('/Aspect[\s-]*ratio:\s*([\d\.]+:[\d\.]+)/i', $movieHtml, $m)) $empty['aspect_ratio'] = trim($m[1]);
if (preg_match('/(\w+)-disc\s+set/i', $movieHtml, $m)) {
$wordToNum = ['single' => 1, 'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5, 'six' => 6];
$empty['number_of_discs'] = $wordToNum[strtolower($m[1])] ?? 1;
} elseif (preg_match('/(\d+)-disc\s+set/i', $movieHtml, $m)) {
$empty['number_of_discs'] = (int)$m[1];
}
if (strpos($movieUrl, '/4k/') !== false || stripos($movieHtml, '4K Ultra HD') !== false) $empty['format'] = '4K Ultra HD';
elseif (strpos($movieUrl, '/3d/') !== false) $empty['format'] = '3D Blu-ray';
else $empty['format'] = 'Blu-ray';
if (preg_match('/src="(https:\/\/images\.static-bluray\.com\/movies\/covers\/\d+_front\.jpg[^"]*)"/i', $movieHtml, $m)) $empty['poster'] = $m[1];
elseif (preg_match('/<img[^>]*class="coverfront"[^>]*src="([^"]+)"/i', $movieHtml, $m)) $empty['poster'] = preg_replace('/_large\.jpg/', '_front.jpg', $m[1]);
return $empty;
}
function fetchFromBlurayComByEan($ean) {
static $lastRequest = 0;
$empty = emptyPhysicalResult();
$ean = preg_replace('/[^0-9]/', '', (string)$ean);
if (strlen($ean) < 8) return $empty;
$now = microtime(true);
if ($lastRequest > 0 && ($now - $lastRequest) < 3) usleep((int)((3 - ($now - $lastRequest)) * 1000000));
$lastRequest = microtime(true);
$searchUrl = "https://www.blu-ray.com/movies/search.php?ean=" . urlencode($ean) . "&action=search";
$ch = curl_init($searchUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
CURLOPT_HTTPHEADER => ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language: fr-FR,fr;q=0.9', 'Referer: https://www.blu-ray.com/']
]);
$searchHtml = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$searchHtml || $httpCode !== 200 || !preg_match('/href="(https:\/\/www\.blu-ray\.com\/movies\/[^"]+\/(\d+)\/)"/i', $searchHtml, $matches)) return $empty;
$movieUrl = $matches[1];
sleep(2);
$ch2 = curl_init($movieUrl);
curl_setopt_array($ch2, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
CURLOPT_HTTPHEADER => ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Referer: https://www.blu-ray.com/']
]);
$movieHtml = curl_exec($ch2);
curl_close($ch2);
if (!$movieHtml) return $empty;
if (preg_match('/<div[^>]*id="movie_info"[^>]*>.*?<h3>([^<]+)<\/h3>/is', $movieHtml, $m)) $empty['title'] = trim($m[1]);
elseif (preg_match('/<h1[^>]*>([^<]+)<\/h1>/i', $movieHtml, $m)) $empty['title'] = trim(preg_replace('/\s*(Blu-ray|4K|3D|DVD|UHD).*$/i', '', trim(strip_tags($m[1]))));
if (preg_match('/<h3[^>]*>([^<]+)<\/h3>\s*(?:&nbsp;)?\((\d{4})\)/i', $movieHtml, $m)) $empty['year'] = $m[2];
if (preg_match('/href="[^"]*studioid=\d+[^"]*"[^>]*>([^<]+)<\/a>/i', $movieHtml, $m)) $empty['publisher'] = trim($m[1]);
if (preg_match('/(\d+)\s*min<\/span>/i', $movieHtml, $m)) $empty['length'] = $m[1] . ' min';
if (preg_match('/Aspect[\s-]*ratio:\s*([\d\.]+:[\d\.]+)/i', $movieHtml, $m)) $empty['aspect_ratio'] = trim($m[1]);
if (preg_match('/(\w+)-disc\s+set/i', $movieHtml, $m)) {
$wordToNum = ['single' => 1, 'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5, 'six' => 6];
$empty['number_of_discs'] = $wordToNum[strtolower($m[1])] ?? 1;
} elseif (preg_match('/(\d+)-disc\s+set/i', $movieHtml, $m)) {
$empty['number_of_discs'] = (int)$m[1];
}
if (strpos($movieUrl, '/4k/') !== false || stripos($movieHtml, '4K Ultra HD') !== false) $empty['format'] = '4K Ultra HD';
elseif (strpos($movieUrl, '/3d/') !== false) $empty['format'] = '3D Blu-ray';
else $empty['format'] = 'Blu-ray';
if (preg_match('/src="(https:\/\/images\.static-bluray\.com\/movies\/covers\/\d+_front\.jpg[^"]*)"/i', $movieHtml, $m)) $empty['poster'] = $m[1];
elseif (preg_match('/<img[^>]*class="coverfront"[^>]*src="([^"]+)"/i', $movieHtml, $m)) $empty['poster'] = preg_replace('/_large\.jpg/', '_front.jpg', $m[1]);
return $empty;
}
// CORRECTION : Fonction helper pour trouver le film le plus populaire disposant d'un poster valide
function findBestTmdbMovie($results) {
if (empty($results) || !is_array($results)) return null;
$bestWithPoster = null;
@@ -352,7 +250,7 @@ function findBestTmdbMovie($results) {
return $bestWithPoster !== null ? $bestWithPoster : $results[0];
}
// CORRECTION MAJEURE : Recherche TMDB intelligente en 4 étapes pour garantir une affiche
// CORRECTION : Recherche TMDB avec découpage générique des sous-titres (séparateurs universels :, -, —, |)
function fetchTmdbPosterAndSynopsis($title, $year = '', $pdo = null) {
$default = ['poster'=>'assets/img/default_physical_media.jpg','title'=>'','description'=>'','director'=>'','actors'=>'','length'=>'','year'=>''];
if (empty($title)) return $default;
@@ -361,46 +259,77 @@ function fetchTmdbPosterAndSynopsis($title, $year = '', $pdo = null) {
if (!$tmdbKey) return $default;
$clean = cleanTitle($title);
$queryUrl = urlencode($clean);
// 1. Recherche principale en français avec l'année
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$queryUrl}&language=fr-FR";
if (!empty($year)) {
$searchUrl .= "&year={$year}";
// Génération automatique des variantes de requêtes de manière générique
$queries = [$clean];
foreach ([':', ' - ', ' — ', ' | '] as $sep) {
if (strpos($clean, $sep) !== false) {
$parts = explode($sep, $clean);
if (!empty(trim($parts[0]))) {
$queries[] = trim($parts[0]);
}
}
}
$queries = array_unique($queries);
$res = httpGet($searchUrl, 8);
$data = $res ? json_decode($res, true) : [];
$movie = !empty($data['results']) ? findBestTmdbMovie($data['results']) : null;
$movie = null;
// 2. Fallback en français SANS l'année (si aucun poster valide trouvé)
if ((empty($movie) || empty($movie['poster_path'])) && !empty($year)) {
$resFallback = httpGet("https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$queryUrl}&language=fr-FR", 8);
$dataFallback = $resFallback ? json_decode($resFallback, true) : [];
if (!empty($dataFallback['results'])) {
$candidate = findBestTmdbMovie($dataFallback['results']);
if (!empty($candidate['poster_path']) || empty($movie)) {
foreach ($queries as $q) {
$queryUrl = urlencode($q);
// 1. Recherche en français avec l'année
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$queryUrl}&language=fr-FR";
if (!empty($year)) {
$searchUrl .= "&year={$year}";
}
$res = httpGet($searchUrl, 8);
$data = $res ? json_decode($res, true) : [];
if (!empty($data['results'])) {
$candidate = findBestTmdbMovie($data['results']);
if (!empty($candidate['poster_path'])) {
$movie = $candidate;
break;
} elseif (empty($movie)) {
$movie = $candidate;
}
}
// 2. Recherche en français sans l'année
if (empty($movie) || empty($movie['poster_path'])) {
$resFallback = httpGet("https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$queryUrl}&language=fr-FR", 8);
$dataFallback = $resFallback ? json_decode($resFallback, true) : [];
if (!empty($dataFallback['results'])) {
$candidate = findBestTmdbMovie($dataFallback['results']);
if (!empty($candidate['poster_path'])) {
$movie = $candidate;
break;
} elseif (empty($movie)) {
$movie = $candidate;
}
}
}
// 3. Recherche globale (VO) sans filtre de langue
if (empty($movie) || empty($movie['poster_path'])) {
$resGlobal = httpGet("https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$queryUrl}", 8);
$dataGlobal = $resGlobal ? json_decode($resGlobal, true) : [];
if (!empty($dataGlobal['results'])) {
$candidate = findBestTmdbMovie($dataGlobal['results']);
if (!empty($candidate['poster_path'])) {
$movie = $candidate;
break;
} elseif (empty($movie)) {
$movie = $candidate;
}
}
}
}
// 3. Fallback SANS restriction de langue (titre original/VO)
if (empty($movie) || empty($movie['poster_path'])) {
$resGlobal = httpGet("https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$queryUrl}", 8);
$dataGlobal = $resGlobal ? json_decode($resGlobal, true) : [];
if (!empty($dataGlobal['results'])) {
$candidate = findBestTmdbMovie($dataGlobal['results']);
if (!empty($candidate['poster_path']) || empty($movie)) {
$movie = $candidate;
}
}
}
// 4. Fallback SANS accents si le titre accentué n'a rien donné
// 4. Dernier recours : sans accents
if (empty($movie) || empty($movie['poster_path'])) {
$noAccentUrl = urlencode(removeAccentsForUrl($clean));
if ($noAccentUrl !== $queryUrl && !empty($noAccentUrl)) {
if (!empty($noAccentUrl)) {
$resNoAccent = httpGet("https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query={$noAccentUrl}", 8);
$dataNoAccent = $resNoAccent ? json_decode($resNoAccent, true) : [];
if (!empty($dataNoAccent['results'])) {
@@ -718,7 +647,7 @@ switch ($action) {
$poster = 'assets/img/default_physical_media.jpg';
$streaming = 'Support physique / Cinéma';
// Appel TMDB intelligent
// Appel TMDB intelligent avec découpage générique des sous-titres
$tmdbData = fetchTmdbPosterAndSynopsis($title, $year, $pdo);
if ($tmdbData) {
if (!empty($tmdbData['director'])) $director = $tmdbData['director'];