Actualiser api.php
This commit is contained in:
@@ -69,7 +69,7 @@ function httpGet($url, $timeout = 3, $ua = null) {
|
||||
$ctx = stream_context_create(['http' => [
|
||||
'timeout' => $timeout,
|
||||
'user_agent' => $ua,
|
||||
'header' => "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: fr-FR,fr;q=0.9\r\n"
|
||||
'header' => "Accept: application/json\r\nAccept-Language: fr-FR,fr;q=0.9\r\n"
|
||||
]]);
|
||||
return @file_get_contents($url, false, $ctx);
|
||||
}
|
||||
@@ -82,10 +82,8 @@ function httpGet($url, $timeout = 3, $ua = null) {
|
||||
CURLOPT_USERAGENT => $ua,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept: application/json',
|
||||
'Accept-Language: fr-FR,fr;q=0.9,en;q=0.8',
|
||||
'Accept-Encoding: identity',
|
||||
'Connection: keep-alive',
|
||||
],
|
||||
]);
|
||||
$res = curl_exec($ch);
|
||||
@@ -115,190 +113,152 @@ function extractYear($dateStr) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// ── DVDBlurayCovers.com Scraper ──
|
||||
function fetchDVDBlurayCovers($title, $year = '', $format = 'bluray') {
|
||||
// ── DVDCover.com via API REST WordPress ──
|
||||
function fetchDVDCover($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);
|
||||
if (empty($cleanTitle)) return null;
|
||||
|
||||
// URL de recherche DVDBlurayCovers
|
||||
$searchUrl = "https://www.dvdbluraycovers.com/?s=" . urlencode($cleanTitle);
|
||||
// API REST WordPress de DVDcover
|
||||
// Endpoint : /wp-json/wp/v2/posts?search=TITRE&_embed
|
||||
$searchUrl = "https://www.dvdcover.com/wp-json/wp/v2/posts?search=" . urlencode($cleanTitle) . "&_embed&per_page=10";
|
||||
|
||||
$html = httpGet($searchUrl, 10, $ua);
|
||||
if (!$html) {
|
||||
error_log("DVDBlurayCovers: Échec recherche pour '$title'");
|
||||
$json = httpGet($searchUrl, 10);
|
||||
if (!$json) {
|
||||
error_log("DVDCover API: Échec requête pour '$title'");
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = [
|
||||
'poster' => '',
|
||||
'title' => '',
|
||||
'format' => $format,
|
||||
];
|
||||
|
||||
// Parser le HTML avec DOMDocument
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($html);
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
// Chercher les liens vers les pages de covers individuelles
|
||||
// DVDBlurayCovers utilise des articles avec des liens vers les covers
|
||||
$links = $xpath->query('//article[contains(@class,"post") or contains(@class,"entry")]//a/@href');
|
||||
|
||||
if ($links->length === 0) {
|
||||
// Fallback : chercher tous les liens qui ressemblent à des pages de covers
|
||||
$links = $xpath->query('//a[contains(@href,"/cover/") or contains(@href,"/covers/") or contains(@href,"/bluray/") or contains(@href,"/dvd/")]');
|
||||
$posts = json_decode($json, true);
|
||||
if (!is_array($posts) || empty($posts)) {
|
||||
error_log("DVDCover API: Aucun résultat pour '$title'");
|
||||
return null;
|
||||
}
|
||||
|
||||
$coverPages = [];
|
||||
foreach ($links as $link) {
|
||||
$href = $link->nodeValue;
|
||||
if (strpos($href, 'http') !== 0) {
|
||||
$href = 'https://www.dvdbluraycovers.com' . $href;
|
||||
}
|
||||
// Éviter les doublons et les pages de catégories/tags
|
||||
if (!in_array($href, $coverPages) &&
|
||||
strpos($href, '/category/') === false &&
|
||||
strpos($href, '/tag/') === false &&
|
||||
strpos($href, '/page/') === false) {
|
||||
$coverPages[] = $href;
|
||||
}
|
||||
if (count($coverPages) >= 5) break; // Limiter à 5 résultats max
|
||||
}
|
||||
$cleanTitleLower = strtolower($cleanTitle);
|
||||
$bestPost = null;
|
||||
$bestScore = 0;
|
||||
|
||||
// Parcourir les pages de covers trouvées
|
||||
foreach ($coverPages as $coverPage) {
|
||||
$coverHtml = httpGet($coverPage, 10, $ua);
|
||||
if (!$coverHtml) continue;
|
||||
|
||||
$domCover = new DOMDocument();
|
||||
@$domCover->loadHTML($coverHtml);
|
||||
$xpathCover = new DOMXPath($domCover);
|
||||
|
||||
// Extraire le titre de la page
|
||||
$coverTitle = '';
|
||||
$titleNodes = $xpathCover->query('//h1[contains(@class,"entry-title") or contains(@class,"post-title")]');
|
||||
if ($titleNodes->length > 0) {
|
||||
$coverTitle = trim($titleNodes->item(0)->textContent);
|
||||
} else {
|
||||
$titleNodes = $xpathCover->query('//title');
|
||||
if ($titleNodes->length > 0) {
|
||||
$coverTitle = trim($titleNodes->item(0)->textContent);
|
||||
// Nettoyer le titre (enlever " - DVDBlurayCovers" etc.)
|
||||
$coverTitle = preg_replace('/\s*[-|]\s*DVDBlurayCovers.*$/i', '', $coverTitle);
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier que le titre correspond au film recherché
|
||||
$coverTitleLower = strtolower($coverTitle);
|
||||
$searchTitleLower = strtolower($cleanTitle);
|
||||
// Parcourir les posts et scorer leur pertinence
|
||||
foreach ($posts as $post) {
|
||||
$postTitle = $post['title']['rendered'] ?? '';
|
||||
$postTitleLower = strtolower($postTitle);
|
||||
|
||||
$score = 0;
|
||||
if (strpos($coverTitleLower, $searchTitleLower) !== false) {
|
||||
|
||||
// Le titre du post contient-il le film recherché ?
|
||||
if (strpos($postTitleLower, $cleanTitleLower) !== false) {
|
||||
$score += 50;
|
||||
}
|
||||
if (!empty($year) && strpos($coverTitle, $year) !== false) {
|
||||
|
||||
// Correspondance de l'année
|
||||
if (!empty($year) && strpos($postTitle, $year) !== false) {
|
||||
$score += 30;
|
||||
}
|
||||
if (stripos($coverTitle, $format) !== false) {
|
||||
|
||||
// Correspondance du format
|
||||
$formatLower = strtolower($format);
|
||||
if (stripos($postTitle, $format) !== false ||
|
||||
stripos($postTitle, str_replace('-', ' ', $format)) !== false) {
|
||||
$score += 20;
|
||||
}
|
||||
|
||||
// Si le score est trop bas, on ignore ce résultat
|
||||
if ($score < 30) {
|
||||
continue;
|
||||
// Bonus si le titre contient "cover" ou "jaquette"
|
||||
if (stripos($postTitle, 'cover') !== false) {
|
||||
$score += 10;
|
||||
}
|
||||
|
||||
// Chercher l'image principale de la jaquette
|
||||
$poster = '';
|
||||
if ($score > $bestScore) {
|
||||
$bestScore = $score;
|
||||
$bestPost = $post;
|
||||
}
|
||||
|
||||
// Méthode 1 : Chercher dans le contenu principal (entry-content)
|
||||
$contentNodes = $xpathCover->query('//div[contains(@class,"entry-content") or contains(@class,"post-content")]//img');
|
||||
if ($contentNodes->length > 0) {
|
||||
foreach ($contentNodes as $img) {
|
||||
$src = $img->getAttribute('src');
|
||||
if (empty($src)) {
|
||||
$src = $img->getAttribute('data-src');
|
||||
}
|
||||
if (empty($src)) {
|
||||
$src = $img->getAttribute('data-lazy-src');
|
||||
}
|
||||
// Score parfait, on arrête
|
||||
if ($score >= 100) break;
|
||||
}
|
||||
|
||||
// Vérifier que c'est une vraie image (pas un logo, icône, etc.)
|
||||
if (!empty($src) &&
|
||||
strpos($src, 'logo') === false &&
|
||||
strpos($src, 'icon') === false &&
|
||||
strpos($src, 'banner') === false &&
|
||||
strpos($src, 'bg') === false &&
|
||||
strpos($src, 'button') === false &&
|
||||
strpos($src, 'social') === false &&
|
||||
(strpos($src, '.jpg') !== false || strpos($src, '.jpeg') !== false || strpos($src, '.png') !== false || strpos($src, '.webp') !== false)) {
|
||||
$poster = $src;
|
||||
// Si aucun post ne correspond assez bien, prendre le premier
|
||||
if (!$bestPost && !empty($posts)) {
|
||||
$bestPost = $posts[0];
|
||||
}
|
||||
|
||||
if (!$bestPost) return null;
|
||||
|
||||
// Extraire l'image du post
|
||||
$poster = '';
|
||||
|
||||
// Méthode 1 : Image mise en avant (_embedded.wp:featuredmedia)
|
||||
if (isset($bestPost['_embedded']['wp:featuredmedia'][0])) {
|
||||
$featured = $bestPost['_embedded']['wp:featuredmedia'][0];
|
||||
// Chercher la plus grande taille disponible
|
||||
if (!empty($featured['media_details']['sizes'])) {
|
||||
$sizes = $featured['media_details']['sizes'];
|
||||
// Ordre de préférence : full > large > medium > thumbnail
|
||||
$preferredSizes = ['full', 'large', 'medium', 'thumbnail'];
|
||||
foreach ($preferredSizes as $size) {
|
||||
if (isset($sizes[$size]['source_url'])) {
|
||||
$poster = $sizes[$size]['source_url'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode 2 : Chercher dans les figures
|
||||
if (empty($poster)) {
|
||||
$figureNodes = $xpathCover->query('//figure//img');
|
||||
if ($figureNodes->length > 0) {
|
||||
foreach ($figureNodes as $img) {
|
||||
$src = $img->getAttribute('src');
|
||||
if (empty($src)) {
|
||||
$src = $img->getAttribute('data-src');
|
||||
}
|
||||
if (!empty($src) &&
|
||||
strpos($src, 'logo') === false &&
|
||||
strpos($src, 'icon') === false &&
|
||||
(strpos($src, '.jpg') !== false || strpos($src, '.jpeg') !== false || strpos($src, '.png') !== false)) {
|
||||
$poster = $src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode 3 : Meta Open Graph
|
||||
if (empty($poster)) {
|
||||
$ogNodes = $xpathCover->query('//meta[@property="og:image"]/@content');
|
||||
if ($ogNodes->length > 0) {
|
||||
$poster = $ogNodes->item(0)->nodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode 4 : Toutes les images dans wp-content/uploads
|
||||
if (empty($poster)) {
|
||||
$allImgs = $xpathCover->query('//img[contains(@src,"wp-content/uploads")]');
|
||||
if ($allImgs->length > 0) {
|
||||
foreach ($allImgs as $img) {
|
||||
$src = $img->getAttribute('src');
|
||||
if (strpos($src, 'logo') === false &&
|
||||
strpos($src, 'icon') === false &&
|
||||
strpos($src, '300x') === false &&
|
||||
strpos($src, '150x') === false) {
|
||||
$poster = $src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Si on a trouvé une image, on la garde
|
||||
if (!empty($poster)) {
|
||||
// S'assurer que l'URL est absolue
|
||||
if (strpos($poster, 'http') !== 0) {
|
||||
$poster = 'https://www.dvdbluraycovers.com' . (strpos($poster, '/') === 0 ? '' : '/') . ltrim($poster, '/');
|
||||
}
|
||||
|
||||
$result['poster'] = $poster;
|
||||
$result['title'] = $coverTitle;
|
||||
break;
|
||||
// Fallback : source_url direct
|
||||
if (empty($poster) && !empty($featured['source_url'])) {
|
||||
$poster = $featured['source_url'];
|
||||
}
|
||||
}
|
||||
|
||||
return (!empty($result['poster'])) ? $result : null;
|
||||
// Méthode 2 : Images dans le contenu du post
|
||||
if (empty($poster) && !empty($bestPost['content']['rendered'])) {
|
||||
$content = $bestPost['content']['rendered'];
|
||||
// Chercher les balises img
|
||||
if (preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) {
|
||||
foreach ($matches[1] as $img) {
|
||||
// Filtrer les images non pertinentes
|
||||
if (strpos($img, 'logo') === false &&
|
||||
strpos($img, 'icon') === false &&
|
||||
strpos($img, 'banner') === false &&
|
||||
strpos($img, 'bg') === false &&
|
||||
strpos($img, 'button') === false &&
|
||||
strpos($img, 'social') === false &&
|
||||
(strpos($img, '.jpg') !== false || strpos($img, '.jpeg') !== false || strpos($img, '.png') !== false || strpos($img, '.webp') !== false)) {
|
||||
$poster = $img;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode 3 : Images embarquées dans _embedded.wp:embedded
|
||||
if (empty($poster) && isset($bestPost['_embedded']['wp:embedded'])) {
|
||||
foreach ($bestPost['_embedded']['wp:embedded'] as $embedded) {
|
||||
if (!empty($embedded['source_url'])) {
|
||||
$poster = $embedded['source_url'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($poster)) {
|
||||
error_log("DVDCover API: Pas d'image trouvée pour le post ID " . ($bestPost['id'] ?? '?'));
|
||||
return null;
|
||||
}
|
||||
|
||||
// S'assurer que l'URL est absolue
|
||||
if (strpos($poster, 'http') !== 0) {
|
||||
$poster = 'https://www.dvdcover.com' . (strpos($poster, '/') === 0 ? '' : '/') . ltrim($poster, '/');
|
||||
}
|
||||
|
||||
// Supprimer les suffixes de taille WordPress pour avoir la version originale
|
||||
// Ex: image-300x200.jpg → image.jpg
|
||||
$poster = preg_replace('/-\d+x\d+(\.\w+)$/', '$1', $poster);
|
||||
|
||||
return [
|
||||
'poster' => $poster,
|
||||
'title' => $bestPost['title']['rendered'] ?? $cleanTitle,
|
||||
'format' => $format,
|
||||
];
|
||||
}
|
||||
|
||||
// ── API TMDB (uniquement pour les critiques) ──
|
||||
@@ -480,9 +440,9 @@ switch ($action) {
|
||||
}
|
||||
|
||||
if ($type === 'videotheque') {
|
||||
// DVDBlurayCovers pour vidéothèque
|
||||
// DVDCover API pour vidéothèque
|
||||
$format = $result['format'] ?: 'Blu-ray';
|
||||
$dcData = fetchDVDBlurayCovers($titleForSearch, $result['year'], $format);
|
||||
$dcData = fetchDVDCover($titleForSearch, $result['year'], $format);
|
||||
if (!empty($dcData)) {
|
||||
if (!empty($dcData['poster'])) $result['poster'] = $dcData['poster'];
|
||||
if (!empty($dcData['title'])) $result['title'] = $dcData['title'];
|
||||
@@ -526,10 +486,10 @@ 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 : DVDBlurayCovers pour la jaquette
|
||||
// Vidéothèque : DVDCover API pour la jaquette
|
||||
if (empty($data['poster']) && !empty($data['title'])) {
|
||||
$format = $data['format'] ?: 'Blu-ray';
|
||||
$dcData = fetchDVDBlurayCovers($data['title'], $data['year'] ?? '', $format);
|
||||
$dcData = fetchDVDCover($data['title'], $data['year'] ?? '', $format);
|
||||
if (!empty($dcData['poster'])) {
|
||||
$data['poster'] = $dcData['poster'];
|
||||
}
|
||||
@@ -634,10 +594,10 @@ switch ($action) {
|
||||
$poster = $rowData['poster'] ?? '';
|
||||
$director = '';
|
||||
|
||||
// Récupération jaquette via DVDBlurayCovers
|
||||
// Récupération jaquette via DVDCover API
|
||||
$cleanTitleForDC = cleanTitle($title);
|
||||
if (!empty($cleanTitleForDC)) {
|
||||
$dcData = fetchDVDBlurayCovers($cleanTitleForDC, $year, $format);
|
||||
$dcData = fetchDVDCover($cleanTitleForDC, $year, $format);
|
||||
if (!empty($dcData)) {
|
||||
if (!empty($dcData['poster'])) {
|
||||
$poster = $dcData['poster'];
|
||||
@@ -685,7 +645,7 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'debug_dvdbluraycovers':
|
||||
case 'debug_dvdcover':
|
||||
$title = $_GET['title'] ?? '';
|
||||
$year = $_GET['year'] ?? '';
|
||||
$format = $_GET['format'] ?? 'Blu-ray';
|
||||
@@ -693,8 +653,53 @@ switch ($action) {
|
||||
if (!$title) { echo json_encode(['error' => 'Titre manquant']); exit; }
|
||||
|
||||
$result = ['title' => $title, 'year' => $year, 'format' => $format];
|
||||
$data = fetchDVDBlurayCovers($title, $year, $format);
|
||||
$result['data'] = $data;
|
||||
|
||||
// Test direct de l'API
|
||||
$cleanTitle = cleanTitle($title);
|
||||
$apiUrl = "https://www.dvdcover.com/wp-json/wp/v2/posts?search=" . urlencode($cleanTitle) . "&_embed&per_page=5";
|
||||
$result['api_url'] = $apiUrl;
|
||||
|
||||
$json = httpGet($apiUrl, 10);
|
||||
if ($json) {
|
||||
$posts = json_decode($json, true);
|
||||
$result['posts_count'] = is_array($posts) ? count($posts) : 0;
|
||||
$result['posts'] = [];
|
||||
|
||||
if (is_array($posts)) {
|
||||
foreach ($posts as $post) {
|
||||
$postData = [
|
||||
'id' => $post['id'] ?? null,
|
||||
'title' => $post['title']['rendered'] ?? '',
|
||||
'link' => $post['link'] ?? '',
|
||||
];
|
||||
|
||||
// Extraire les images
|
||||
$imgs = [];
|
||||
if (isset($post['_embedded']['wp:featuredmedia'][0])) {
|
||||
$featured = $post['_embedded']['wp:featuredmedia'][0];
|
||||
if (!empty($featured['source_url'])) {
|
||||
$imgs[] = $featured['source_url'];
|
||||
}
|
||||
if (!empty($featured['media_details']['sizes'])) {
|
||||
foreach ($featured['media_details']['sizes'] as $size => $data) {
|
||||
if (!empty($data['source_url'])) {
|
||||
$imgs[] = $data['source_url'] . " ($size)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$postData['images'] = $imgs;
|
||||
|
||||
$result['posts'][] = $postData;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result['api_error'] = 'Impossible de joindre l\'API';
|
||||
}
|
||||
|
||||
// Test de la fonction complète
|
||||
$data = fetchDVDCover($title, $year, $format);
|
||||
$result['fetch_result'] = $data;
|
||||
$result['status'] = $data ? 'OK' : 'AUCUN_RÉSULTAT';
|
||||
|
||||
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
Reference in New Issue
Block a user