From 6051a91cab3b0e32155d9add5303719adf3c8a49 Mon Sep 17 00:00:00 2001 From: Cedric Date: Fri, 24 Jul 2026 11:18:48 +0200 Subject: [PATCH] Actualiser api.php --- api.php | 201 ++++++++++++++++++-------------------------------------- 1 file changed, 65 insertions(+), 136 deletions(-) diff --git a/api.php b/api.php index 8e53003..9e4f32c 100644 --- a/api.php +++ b/api.php @@ -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>\s*(?: )?\((\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('/]*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('/]*id="movie_info"[^>]*>.*?

([^<]+)<\/h3>/is', $movieHtml, $m)) $empty['title'] = trim($m[1]); - elseif (preg_match('/]*>([^<]+)<\/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>\s*(?: )?\((\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('/]*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}"; - } - - $res = httpGet($searchUrl, 8); - $data = $res ? json_decode($res, true) : []; - $movie = !empty($data['results']) ? findBestTmdbMovie($data['results']) : 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)) { - $movie = $candidate; + // 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]); } } } - - // 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)) { + $queries = array_unique($queries); + + $movie = null; + + 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; + } } } } - // 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'];