Actualiser api.php
This commit is contained in:
@@ -93,6 +93,25 @@ function httpGet($url, $timeout = 3, $ua = null) {
|
||||
return $res ?: null;
|
||||
}
|
||||
|
||||
// Vérifie si une URL existe (HEAD request)
|
||||
function urlExists($url, $timeout = 3) {
|
||||
if (!function_exists('curl_init')) return false;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_NOBODY => true,
|
||||
CURLOPT_TIMEOUT => $timeout,
|
||||
CURLOPT_CONNECTTIMEOUT => 2,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
]);
|
||||
curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
return ($code >= 200 && $code < 400);
|
||||
}
|
||||
|
||||
function cleanTitle($title) {
|
||||
$clean = preg_replace('/\s*[\[\(].*?[\]\)]\s*/', '', $title);
|
||||
$clean = preg_replace('/\s*-\s*(Édition|Edition|Collector|Simple|Spéciale|Digibook|Ultimate|Intégrale|Combo|SteelBook|Boîtier).*$/i', '', $clean);
|
||||
@@ -115,98 +134,101 @@ function extractYear($dateStr) {
|
||||
return '';
|
||||
}
|
||||
|
||||
function fetchDVDCover($title, $year = '', $format = 'bluray') {
|
||||
// ── COVERCENTURY.COM ──
|
||||
// Structure : https://www.covercentury.com/covers/{format}/{première_lettre}/{Nom_Normalisé}{numéro}.jpg
|
||||
// Exemple : https://www.covercentury.com/covers/dvd/t/The_Matrix_Reloaded1.jpg
|
||||
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);
|
||||
$searchUrl = "https://www.dvdcover.com/?s=" . urlencode($cleanTitle);
|
||||
if (empty($cleanTitle)) return null;
|
||||
|
||||
$html = httpGet($searchUrl, 10, $ua);
|
||||
if (!$html) {
|
||||
error_log("DVDCover: Erreur réseau pour '$title'");
|
||||
return null;
|
||||
}
|
||||
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($html);
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
// Les résultats sont dans des <h2><a>
|
||||
$links = $xpath->query('//h2//a');
|
||||
if ($links->length === 0) {
|
||||
error_log("DVDCover: Aucun lien H2 trouvé pour '$title'");
|
||||
return null;
|
||||
}
|
||||
|
||||
// On cherche le meilleur lien : correspondance titre + année si possible
|
||||
$bestUrl = null;
|
||||
$cleanTitleLower = strtolower($cleanTitle);
|
||||
|
||||
foreach ($links as $a) {
|
||||
$text = strtolower(trim($a->textContent));
|
||||
$href = $a->getAttribute('href');
|
||||
|
||||
// Priorité : correspond au titre ET à l'année
|
||||
if (!empty($year) && strpos($text, strtolower($cleanTitleLower)) !== false && strpos($text, $year) !== false) {
|
||||
$bestUrl = $href;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fallback : correspond au titre seul (premier trouvé)
|
||||
if ($bestUrl === null && strpos($text, $cleanTitleLower) !== false) {
|
||||
$bestUrl = $href;
|
||||
}
|
||||
}
|
||||
|
||||
// Dernier fallback : premier lien de la liste
|
||||
if (!$bestUrl) {
|
||||
$bestUrl = $links->item(0)->getAttribute('href');
|
||||
}
|
||||
|
||||
if (!$bestUrl) return null;
|
||||
|
||||
// On scrape la page de la fiche
|
||||
$coverHtml = httpGet($bestUrl, 10, $ua);
|
||||
if (!$coverHtml) return null;
|
||||
|
||||
$domFiche = new DOMDocument();
|
||||
@$domFiche->loadHTML($coverHtml);
|
||||
$xpathFiche = new DOMXPath($domFiche);
|
||||
|
||||
// On cherche la plus grande image dans wp-content/uploads (pas les thumbnails -300x)
|
||||
$imgs = $xpathFiche->query('//img[contains(@src,"wp-content/uploads")]');
|
||||
$bestSrc = null;
|
||||
$bestSize = 0;
|
||||
|
||||
foreach ($imgs as $img) {
|
||||
$src = $img->getAttribute('src');
|
||||
|
||||
// Ignorer logos, icônes et thumbnails redimensionnés
|
||||
if (strpos($src, 'logo') !== false) continue;
|
||||
if (strpos($src, 'icon') !== false) continue;
|
||||
|
||||
// Préférer les images sans suffixe de redimensionnement (ex: -300x201)
|
||||
$isThumb = preg_match('/-\d+x\d+\./', $src);
|
||||
|
||||
// Tenter de récupérer la version pleine taille (supprimer le suffixe -WxH)
|
||||
$fullSrc = preg_replace('/-\d+x\d+(\.\w+)$/', '$1', $src);
|
||||
|
||||
// Scorer : pleine taille > thumbnail
|
||||
$score = $isThumb ? 1 : 10;
|
||||
if ($score > $bestSize) {
|
||||
$bestSize = $score;
|
||||
$bestSrc = $fullSrc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bestSrc) return null;
|
||||
|
||||
return [
|
||||
'poster' => $bestSrc,
|
||||
'title' => $cleanTitle,
|
||||
'format' => $format
|
||||
// Mapping des formats pour CoverCentury
|
||||
$formatMap = [
|
||||
'4k ultra hd' => '4kultrahd',
|
||||
'4k' => '4kultrahd',
|
||||
'blu-ray' => 'bluray',
|
||||
'bluray' => 'bluray',
|
||||
'dvd' => 'dvd',
|
||||
];
|
||||
$ccFormat = $formatMap[strtolower($format)] ?? 'bluray';
|
||||
|
||||
// Normaliser le titre pour CoverCentury
|
||||
// Ex: "The Matrix" → "The_Matrix"
|
||||
// CoverCentury utilise souvent le titre anglais, on va essayer plusieurs variantes
|
||||
$titleVariants = [];
|
||||
|
||||
// Variante 1 : titre original nettoyé
|
||||
$normalized = $cleanTitle;
|
||||
$normalized = preg_replace('/[^a-zA-Z0-9\s]/', '', $normalized);
|
||||
$normalized = trim($normalized);
|
||||
$normalized = preg_replace('/\s+/', '_', $normalized);
|
||||
if (!empty($normalized)) $titleVariants[] = $normalized;
|
||||
|
||||
// Variante 2 : sans article au début (The, Le, La, Les)
|
||||
$withoutArticle = preg_replace('/^(The|Le|La|Les|Un|Une|A)\s+/i', '', $cleanTitle);
|
||||
$withoutArticle = preg_replace('/[^a-zA-Z0-9\s]/', '', $withoutArticle);
|
||||
$withoutArticle = trim($withoutArticle);
|
||||
$withoutArticle = preg_replace('/\s+/', '_', $withoutArticle);
|
||||
if (!empty($withoutArticle) && $withoutArticle !== $normalized) {
|
||||
$titleVariants[] = $withoutArticle;
|
||||
}
|
||||
|
||||
// Variante 3 : ajouter l'article "The_" si absent
|
||||
if (!preg_match('/^The_/i', $normalized)) {
|
||||
$withThe = 'The_' . $normalized;
|
||||
if (!in_array($withThe, $titleVariants)) {
|
||||
$titleVariants[] = $withThe;
|
||||
}
|
||||
}
|
||||
|
||||
// Construire toutes les URLs candidates
|
||||
$candidates = [];
|
||||
foreach ($titleVariants as $variant) {
|
||||
if (empty($variant)) continue;
|
||||
$firstLetter = strtolower(substr($variant, 0, 1));
|
||||
|
||||
// Essayer avec différents suffixes numériques (1, 2, 3, etc.)
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$candidates[] = "https://www.covercentury.com/covers/{$ccFormat}/{$firstLetter}/{$variant}{$i}.jpg";
|
||||
}
|
||||
// Et sans numéro
|
||||
$candidates[] = "https://www.covercentury.com/covers/{$ccFormat}/{$firstLetter}/{$variant}.jpg";
|
||||
}
|
||||
|
||||
// Tester chaque URL
|
||||
foreach ($candidates as $url) {
|
||||
if (urlExists($url, 2)) {
|
||||
return [
|
||||
'poster' => $url,
|
||||
'title' => $cleanTitle,
|
||||
'format' => $format,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Si aucun format ne marche, essayer les autres formats
|
||||
$otherFormats = ['dvd', 'bluray', '4kultrahd'];
|
||||
foreach ($otherFormats as $altFormat) {
|
||||
if ($altFormat === $ccFormat) continue;
|
||||
foreach ($titleVariants as $variant) {
|
||||
if (empty($variant)) continue;
|
||||
$firstLetter = strtolower(substr($variant, 0, 1));
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
$url = "https://www.covercentury.com/covers/{$altFormat}/{$firstLetter}/{$variant}{$i}.jpg";
|
||||
if (urlExists($url, 2)) {
|
||||
return [
|
||||
'poster' => $url,
|
||||
'title' => $cleanTitle,
|
||||
'format' => $format,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error_log("CoverCentury: Aucune jaquette trouvée pour '$title'");
|
||||
return null;
|
||||
}
|
||||
|
||||
// ── API TMDB (uniquement pour les critiques) ──
|
||||
@@ -387,12 +409,12 @@ switch ($action) {
|
||||
}
|
||||
|
||||
if ($type === 'videotheque') {
|
||||
// DVDCover pour vidéothèque
|
||||
// CoverCentury pour vidéothèque
|
||||
$format = $result['format'] ?: 'Blu-ray';
|
||||
$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'];
|
||||
$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 {
|
||||
@@ -433,12 +455,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 : DVDCover pour la jaquette
|
||||
// Vidéothèque : CoverCentury pour la jaquette
|
||||
if (empty($data['poster']) && !empty($data['title'])) {
|
||||
$format = $data['format'] ?: 'Blu-ray';
|
||||
$dcData = fetchDVDCover($data['title'], $data['year'] ?? '', $format);
|
||||
if (!empty($dcData['poster'])) {
|
||||
$data['poster'] = $dcData['poster'];
|
||||
$ccData = fetchCoverCentury($data['title'], $data['year'] ?? '', $format);
|
||||
if (!empty($ccData['poster'])) {
|
||||
$data['poster'] = $ccData['poster'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,16 +536,16 @@ switch ($action) {
|
||||
$poster = $rowData['poster'] ?? '';
|
||||
$director = '';
|
||||
|
||||
// Récupération jaquette via DVDCover
|
||||
$cleanTitleForDC = cleanTitle($title);
|
||||
if (!empty($cleanTitleForDC)) {
|
||||
$dcData = fetchDVDCover($cleanTitleForDC, $year, $format);
|
||||
if (!empty($dcData)) {
|
||||
if (!empty($dcData['poster'])) {
|
||||
$poster = $dcData['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($dcData['title']) && ($title === 'Sans titre' || empty($title))) {
|
||||
$title = $dcData['title'];
|
||||
if (!empty($ccData['title']) && ($title === 'Sans titre' || empty($title))) {
|
||||
$title = $ccData['title'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -590,141 +612,34 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'debug_dvdcover':
|
||||
case 'debug_covercentury':
|
||||
$title = $_GET['title'] ?? '';
|
||||
$year = $_GET['year'] ?? '';
|
||||
$year = $_GET['year'] ?? '';
|
||||
$format = $_GET['format'] ?? 'Blu-ray';
|
||||
|
||||
if (!$title) { echo json_encode(['error' => 'Titre manquant']); exit; }
|
||||
|
||||
$ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
||||
$searchUrl = "https://www.dvdcover.com/?s=" . urlencode(cleanTitle($title));
|
||||
$result = ['title' => $title, 'year' => $year, 'format' => $format];
|
||||
|
||||
$html = httpGet($searchUrl, 10, $ua);
|
||||
// Afficher les variantes testées
|
||||
$cleanTitle = cleanTitle($title);
|
||||
$normalized = preg_replace('/[^a-zA-Z0-9\s]/', '', $cleanTitle);
|
||||
$normalized = trim(preg_replace('/\s+/', '_', $normalized));
|
||||
$withoutArticle = preg_replace('/^(The|Le|La|Les|Un|Une|A)\s+/i', '', $cleanTitle);
|
||||
$withoutArticle = preg_replace('/[^a-zA-Z0-9\s]/', '', $withoutArticle);
|
||||
$withoutArticle = trim(preg_replace('/\s+/', '_', $withoutArticle));
|
||||
|
||||
$diag = [
|
||||
'url' => $searchUrl,
|
||||
'html_length' => $html ? strlen($html) : 0,
|
||||
'html_snippet' => $html ? substr(strip_tags($html), 0, 500) : 'VIDE/ERREUR',
|
||||
'cloudflare' => ($html && strpos($html, 'cloudflare') !== false) ? true : false,
|
||||
'captcha' => ($html && strpos($html, 'captcha') !== false) ? true : false,
|
||||
$result['variants'] = [
|
||||
'normalized' => $normalized,
|
||||
'without_article' => $withoutArticle,
|
||||
];
|
||||
|
||||
// Cherche les articles si HTML reçu
|
||||
if ($html) {
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($html);
|
||||
$xpath = new DOMXPath($dom);
|
||||
$links = $xpath->query('//article[contains(@class,"post")]//a/@href');
|
||||
$diag['articles_found'] = $links->length;
|
||||
$data = fetchCoverCentury($title, $year, $format);
|
||||
$result['data'] = $data;
|
||||
$result['status'] = $data ? 'OK' : 'AUCUN_RÉSULTAT';
|
||||
|
||||
// Essai avec d'autres sélecteurs courants
|
||||
$diag['alt1_h2_links'] = $xpath->query('//h2//a/@href')->length;
|
||||
$h2Links = $xpath->query('//h2//a');
|
||||
$diag['h2_links_list'] = [];
|
||||
foreach ($h2Links as $a) {
|
||||
$diag['h2_links_list'][] = [
|
||||
'text' => trim($a->textContent),
|
||||
'href' => $a->getAttribute('href')
|
||||
];
|
||||
}
|
||||
|
||||
// Et les imgs disponibles dans la page
|
||||
$allImgs = $xpath->query('//img/@src');
|
||||
$diag['img_samples'] = [];
|
||||
$i = 0;
|
||||
foreach ($allImgs as $img) {
|
||||
if ($i++ >= 15) break;
|
||||
$diag['img_samples'][] = $img->nodeValue;
|
||||
}
|
||||
$diag['alt2_figure_imgs'] = $xpath->query('//figure//img/@src')->length;
|
||||
$diag['alt3_any_article'] = $xpath->query('//article')->length;
|
||||
}
|
||||
|
||||
echo json_encode($diag, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
break;
|
||||
|
||||
case 'test_dvdfr':
|
||||
$title = urlencode($_GET['title'] ?? 'Matrix');
|
||||
$url = "https://www.dvdfr.com/recherche/?q={$title}";
|
||||
$html = httpGet($url, 5);
|
||||
if (!$html) { echo json_encode(['error' => 'ERREUR réseau']); break; }
|
||||
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($html);
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
// Cherche tous les liens qui ressemblent à des fiches produit
|
||||
$allLinks = $xpath->query('//a[contains(@href,"/dvd/") or contains(@href,"/film/") or contains(@href,"/bluray/")]');
|
||||
$links = [];
|
||||
foreach ($allLinks as $a) {
|
||||
$href = $a->getAttribute('href');
|
||||
$text = trim($a->textContent);
|
||||
if (!in_array($href, array_column($links, 'href')) && !empty($text)) {
|
||||
$links[] = ['text' => substr($text, 0, 80), 'href' => $href];
|
||||
}
|
||||
if (count($links) >= 10) break;
|
||||
}
|
||||
|
||||
// Cherche les images produit
|
||||
$imgs = $xpath->query('//img[contains(@src,"cover") or contains(@src,"dvd") or contains(@src,"blu") or contains(@src,"jaquette")]');
|
||||
$imgList = [];
|
||||
foreach ($imgs as $img) {
|
||||
$imgList[] = $img->getAttribute('src');
|
||||
if (count($imgList) >= 10) break;
|
||||
}
|
||||
|
||||
// Fallback : toutes les images wp-content ou cdn
|
||||
if (empty($imgList)) {
|
||||
$imgs2 = $xpath->query('//img/@src');
|
||||
foreach ($imgs2 as $img) {
|
||||
$imgList[] = $img->nodeValue;
|
||||
if (count($imgList) >= 15) break;
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'url' => $url,
|
||||
'links' => $links,
|
||||
'imgs' => $imgList
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
break;
|
||||
|
||||
case 'test_covercentury':
|
||||
$title = $_GET['title'] ?? 'Matrix';
|
||||
$urls = [
|
||||
"https://www.covercentury.com/index.php?p=dvdcovers&recherche=" . urlencode($title),
|
||||
"https://www.covercentury.com/index.php?p=blu-raycovers&recherche=" . urlencode($title),
|
||||
"https://www.covercentury.com/index.php?p=dvdcovers&q=" . urlencode($title),
|
||||
"https://www.covercentury.com/index.php?p=dvdcovers&s=" . urlencode($title),
|
||||
];
|
||||
|
||||
$results = [];
|
||||
foreach ($urls as $url) {
|
||||
$html = httpGet($url, 8);
|
||||
if (!$html) { $results[] = ['url' => $url, 'length' => 0, 'snippet' => 'ERREUR']; continue; }
|
||||
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($html);
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
$allImgs = $xpath->query('//img');
|
||||
$imgs = [];
|
||||
foreach ($allImgs as $img) {
|
||||
$src = $img->getAttribute('src');
|
||||
if (strpos($src, 'logo') === false && strpos($src, 'assets') === false) {
|
||||
$imgs[] = ['src' => $src, 'alt' => $img->getAttribute('alt')];
|
||||
}
|
||||
if (count($imgs) >= 10) break;
|
||||
}
|
||||
|
||||
$results[] = [
|
||||
'url' => $url,
|
||||
'length' => strlen($html),
|
||||
'imgs' => $imgs
|
||||
];
|
||||
}
|
||||
echo json_encode($results, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
break;
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user