diff --git a/api.php b/api.php index e5eb384..8516fce 100644 --- a/api.php +++ b/api.php @@ -117,73 +117,14 @@ function extractYear($dateStr) { return ''; } -// ── MovieCovers.com (jaquettes HD pour la vidéothèque) ── -function fetchMovieCovers($title, $year = '', $format = 'Blu-ray') { +// ── CoverCentury.com (jaquettes HD pour vidéothèque) ── +function fetchCoverCentury($title, $year = '', $format = 'bluray') { if (empty($title)) return null; $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'; $cleanTitle = cleanTitle($title); - // MovieCovers utilise des URLs de recherche - $searchUrl = "https://moviecovers.com/search?q=" . urlencode($cleanTitle); - if (!empty($year)) { - $searchUrl .= "+(" . $year . ")"; - } - - $html = httpGet($searchUrl, 8, $ua); - if (!$html) { - error_log("MovieCovers: Échec recherche pour '$title'"); - return null; - } - - $result = [ - 'poster' => '', - 'title' => '', - 'format' => $format, - ]; - - // Extraction des liens d'images depuis la page de résultats - // MovieCovers utilise des liens vers des images en haute résolution - preg_match_all('/href=["\']([^"\']*\/covers?\/[^"\']+\.jpg)["\']/i', $html, $matches); - - if (!empty($matches[1])) { - // Prendre la première image trouvée (généralement la plus pertinente) - $result['poster'] = $matches[1][0]; - - // Essayer de trouver une version HD si disponible - foreach ($matches[1] as $imgUrl) { - if (strpos($imgUrl, 'hd') !== false || strpos($imgUrl, 'large') !== false) { - $result['poster'] = $imgUrl; - break; - } - } - } - - // Si pas trouvé avec le pattern précédent, chercher dans les balises img - if (empty($result['poster'])) { - preg_match_all('/]+src=["\']([^"\']*\/covers?\/[^"\']+\.jpg)["\'][^>]*>/i', $html, $imgMatches); - if (!empty($imgMatches[1])) { - $result['poster'] = $imgMatches[1][0]; - } - } - - // Extraire le titre depuis la page si disponible - if (preg_match('/]*>([^<]+) - MovieCovers/i', $html, $titleMatch)) { - $result['title'] = trim($titleMatch[1]); - } - - return (!empty($result['poster'])) ? $result : null; -} - -// Fonction alternative pour recherche directe par URL si on connaît le format -function fetchMovieCoversDirect($title, $format = 'bluray') { - if (empty($title)) return null; - - $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'; - $cleanTitle = strtolower(trim(preg_replace('/[^a-zA-Z0-9\s]/', '', $title))); - $cleanTitle = preg_replace('/\s+/', '-', $cleanTitle); - - // Formats supportés par MovieCovers + // Mapping des formats pour CoverCentury $formatMap = [ '4k ultra hd' => '4k', '4k' => '4k', @@ -192,15 +133,18 @@ function fetchMovieCoversDirect($title, $format = 'bluray') { 'dvd' => 'dvd', ]; - $mcFormat = $formatMap[strtolower($format)] ?? 'bluray'; + $ccFormat = $formatMap[strtolower($format)] ?? 'bluray'; - // URL directe vers la page du cover - $directUrl = "https://moviecovers.com/{$mcFormat}/{$cleanTitle}"; - $html = httpGet($directUrl, 8, $ua); + // URL de recherche CoverCentury + $searchUrl = "https://www.covercentury.com/search?q=" . urlencode($cleanTitle); + if (!empty($year)) { + $searchUrl .= "+(" . $year . ")"; + } + $html = httpGet($searchUrl, 8, $ua); if (!$html) { - // Fallback sur la recherche - return fetchMovieCovers($title, '', $format); + error_log("CoverCentury: Échec recherche pour '$title'"); + return null; } $result = [ @@ -209,11 +153,47 @@ function fetchMovieCoversDirect($title, $format = 'bluray') { 'format' => $format, ]; - // Chercher l'image principale en haute qualité - if (preg_match('/]+src=["\']([^"\']+\.jpg)["\'][^>]*class=["\'][^"\']*cover[^"\']*["\']/i', $html, $m)) { - $result['poster'] = $m[1]; - } elseif (preg_match('/]+property=["\']og:image["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $m)) { - $result['poster'] = $m[1]; + // Extraction des liens d'images - CoverCentury utilise des structures spécifiques + // Chercher les liens vers les pages de covers + preg_match_all('/href=["\']([^"\']*\/cover\/[^"\']+)["\']/i', $html, $coverLinks); + + if (!empty($coverLinks[1])) { + // Prendre le premier résultat pertinent + $coverPage = $coverLinks[1][0]; + if (strpos($coverPage, 'http') !== 0) { + $coverPage = 'https://www.covercentury.com' . $coverPage; + } + + // Récupérer la page du cover pour avoir l'image en haute qualité + $coverHtml = httpGet($coverPage, 8, $ua); + if ($coverHtml) { + // Chercher l'image principale en haute résolution + if (preg_match('/]+src=["\']([^"\']+\.jpg)["\'][^>]*class=["\'][^"\']*main[^"\']*["\']/i', $coverHtml, $m)) { + $result['poster'] = $m[1]; + } elseif (preg_match('/]+property=["\']og:image["\'][^>]+content=["\']([^"\']+)["\']/i', $coverHtml, $m)) { + $result['poster'] = $m[1]; + } elseif (preg_match('/href=["\']([^"\']*\/images\/[^"\']+\.jpg)["\']/i', $coverHtml, $m)) { + $result['poster'] = $m[1]; + } + + // Extraire le titre + if (preg_match('/]*>([^<]+) - CoverCentury/i', $coverHtml, $titleMatch)) { + $result['title'] = trim($titleMatch[1]); + } + } + } + + // Fallback : chercher directement les images dans la page de résultats + if (empty($result['poster'])) { + preg_match_all('/]+src=["\']([^"\']+\.jpg)["\'][^>]*>/i', $html, $imgMatches); + if (!empty($imgMatches[1])) { + foreach ($imgMatches[1] as $img) { + if (strpos($img, 'covercentury') !== false || strpos($img, '/covers/') !== false) { + $result['poster'] = $img; + break; + } + } + } } return (!empty($result['poster'])) ? $result : null; @@ -366,13 +346,12 @@ switch ($action) { 'length' => '', 'number_of_discs' => 1, 'aspect_ratio' => '', 'actors' => '' ]; - // Pour MovieCovers, on a besoin d'un titre - // On essaie d'abord de trouver le titre via TMDB (pour les critiques) ou on utilise l'EAN comme base + // Pour CoverCentury, on a besoin d'un titre $tmdbKey = getTmdbApiKey($pdo); $titleForSearch = ''; - if ($type === 'critique' && $tmdbKey) { - // Pour les critiques, on cherche d'abord sur TMDB + if ($tmdbKey) { + // Essayer de trouver via TMDB d'abord $searchUrl = "https://api.themoviedb.org/3/find/{$ean}?api_key={$tmdbKey}&external_source=imdb_id"; $searchRes = httpGet($searchUrl, 5); $searchData = $searchRes ? json_decode($searchRes, true) : []; @@ -386,23 +365,23 @@ switch ($action) { } } - // Si pas de titre trouvé, on utilise l'EAN comme référence (peu probable de trouver sur MovieCovers) if (empty($titleForSearch)) { - echo json_encode(['success' => true, 'data' => $result, 'warning' => 'Titre non trouvé pour cet EAN']); + echo json_encode(['success' => true, 'data' => $result, 'warning' => 'Titre non trouvé']); exit; } - // Récupération jaquette via MovieCovers (pour vidéothèque) ou TMDB (pour critiques) + // Récupération jaquette if ($type === 'videotheque') { + // CoverCentury pour vidéothèque $format = $result['format'] ?: 'Blu-ray'; - $mcData = fetchMovieCovers($titleForSearch, $result['year'], $format); - if (!empty($mcData)) { - if (!empty($mcData['poster'])) $result['poster'] = $mcData['poster']; - if (!empty($mcData['title'])) $result['title'] = $mcData['title']; + $ccData = fetchCoverCentury($titleForSearch, $result['year'], $format); + if (!empty($ccData)) { + if (!empty($ccData['poster'])) $result['poster'] = $ccData['poster']; + if (!empty($ccData['title'])) $result['title'] = $ccData['title']; $result['format'] = $format; } } else { - // Critiques : TMDB complet + // TMDB pour critiques if ($tmdbKey) { $tmdbData = fetchTMDBFull($titleForSearch, $result['year'], $tmdbKey, $pdo); if ($tmdbData) { @@ -441,12 +420,12 @@ switch ($action) { $stmt = $pdo->prepare($sql); $stmt->execute([$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $data['poster'] ?? '', $data['rating'] ?? 3.0, $data['review'] ?? '', $streaming]); } else { - // Vidéothèque : MovieCovers pour la jaquette + // Vidéothèque : CoverCentury pour la jaquette if (empty($data['poster']) && !empty($data['title'])) { $format = $data['format'] ?: 'Blu-ray'; - $mcData = fetchMovieCovers($data['title'], $data['year'] ?? '', $format); - if (!empty($mcData['poster'])) { - $data['poster'] = $mcData['poster']; + $ccData = fetchCoverCentury($data['title'], $data['year'] ?? '', $format); + if (!empty($ccData['poster'])) { + $data['poster'] = $ccData['poster']; } } @@ -491,7 +470,7 @@ switch ($action) { $id = makeStableId($type, $title, $year); if ($type === 'videotheque') { - // ── VIDÉOTHÈQUE : MovieCovers pour jaquette HD, PAS de TMDB ── + // ── VIDÉOTHÈQUE : CoverCentury pour jaquette HD ── $csvActors = $rowData['ensemble'] ?? $rowData['creators'] ?? ''; $actors = ''; if (!empty($csvActors)) { @@ -523,21 +502,21 @@ switch ($action) { $poster = $rowData['poster'] ?? ''; $director = ''; - // Récupération jaquette via MovieCovers - $cleanTitleForMC = cleanTitle($title); - if (!empty($cleanTitleForMC)) { - $mcData = fetchMovieCovers($cleanTitleForMC, $year, $format); - if (!empty($mcData)) { - if (!empty($mcData['poster'])) { - $poster = $mcData['poster']; + // Récupération jaquette via CoverCentury + $cleanTitleForCC = cleanTitle($title); + if (!empty($cleanTitleForCC)) { + $ccData = fetchCoverCentury($cleanTitleForCC, $year, $format); + if (!empty($ccData)) { + if (!empty($ccData['poster'])) { + $poster = $ccData['poster']; } - if (!empty($mcData['title']) && ($title === 'Sans titre' || empty($title))) { - $title = $mcData['title']; + if (!empty($ccData['title']) && ($title === 'Sans titre' || empty($title))) { + $title = $ccData['title']; } } } - // PAS D'APPEL TMDB POUR LA VIDÉOTHÈQUE + // PAS DE TMDB POUR VIDÉOTHÈQUE $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description, actors) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) @@ -602,7 +581,7 @@ switch ($action) { } break; - case 'debug_moviecovers': + case 'debug_covercentury': $title = $_GET['title'] ?? ''; $year = $_GET['year'] ?? ''; $format = $_GET['format'] ?? 'Blu-ray'; @@ -610,7 +589,7 @@ switch ($action) { if (!$title) { echo json_encode(['error' => 'Titre manquant']); exit; } $result = ['title' => $title, 'year' => $year, 'format' => $format]; - $data = fetchMovieCovers($title, $year, $format); + $data = fetchCoverCentury($title, $year, $format); $result['data'] = $data; $result['status'] = $data ? 'OK' : 'AUCUN_RÉSULTAT';