From 4b482f4a9a22608c7c0716606953715990e3248e Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 2 Jul 2026 15:57:37 +0200 Subject: [PATCH] Actualiser api.php --- api.php | 214 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 119 insertions(+), 95 deletions(-) diff --git a/api.php b/api.php index 8f439c5..6e86e28 100644 --- a/api.php +++ b/api.php @@ -116,26 +116,27 @@ function emptyPhysicalResult() { ]; } -// ── NOUVELLE FONCTION : SCRAPPING GO-UPC.COM ── +// ── NOUVELLE FONCTION : SCRAPPING GO-UPC.COM (MODIFIÉE) ── function fetchFromGoUpc($ean) { $empty = emptyPhysicalResult(); $url = "https://go-upc.com/search?q=" . urlencode($ean); $html = httpGet($url, 15); if (!$html) return $empty; - // Recherche du titre dans les résultats - if (preg_match('/]*>([^<]+)<\/h1>/i', $html, $m)) { + // Recherche du titre dans h1.product-name + if (preg_match('/]*class="product-name"[^>]*>([^<]+)<\/h1>/i', $html, $m)) { $empty['title'] = trim(strip_tags($m[1])); } elseif (preg_match('/]*>([^<]+)<\/title>/i', $html, $m)) { $title = trim($m[1]); - $title = preg_replace('/\s*[-–]\s*GO-UPC.*$/i', '', $title); + $title = preg_replace('/\s*[-–]\s*Go-UPC.*$/i', '', $title); $empty['title'] = $title; } - // Recherche de l'image - if (preg_match('/]*src="([^"]+\.(?:jpg|jpeg|png|webp))"[^>]*alt="[^"]*product[^"]*"[^>]*>/i', $html, $m)) { + // ✅ RÉCUPÉRATION DE L'IMAGE DEPUIS GO-UPC + // Chercher dans les figures product-image + if (preg_match('/]*class="product-image[^"]*"[^>]*>.*?]*src="([^"]+\.(?:jpg|jpeg|png|webp))"/is', $html, $m)) { $empty['poster'] = trim($m[1]); - } elseif (preg_match('/]*property="og:image"[^>]*content="([^"]+)"/i', $html, $m)) { + } elseif (preg_match('/]*src="([^"]+go-upc\.s3\.amazonaws\.com[^"]+)"/i', $html, $m)) { $empty['poster'] = trim($m[1]); } @@ -152,7 +153,7 @@ function fetchFromGoUpc($ean) { return $empty; } -// ── NOUVELLE FONCTION : SCRAPPING UPCINDEX.COM ── +// ── NOUVELLE FONCTION : SCRAPPING UPCINDEX.COM (MODIFIÉE AVEC MÉTADONNÉES) ── function fetchFromUpcIndex($ean) { $empty = emptyPhysicalResult(); $url = "https://www.upcindex.com/" . urlencode($ean); @@ -160,19 +161,63 @@ function fetchFromUpcIndex($ean) { if (!$html) return $empty; // Recherche du titre - if (preg_match('/]*>([^<]+)<\/h1>/i', $html, $m)) { + if (preg_match('/]*class="text-center"[^>]*>.*?]*itemprop="name"[^>]*>([^<]+)<\/span>/is', $html, $m)) { $empty['title'] = trim(strip_tags($m[1])); } elseif (preg_match('/]*>([^<]+)<\/title>/i', $html, $m)) { $title = trim($m[1]); - $title = preg_replace('/\s*[-–]\s*UPCIndex.*$/i', '', $title); + $title = preg_replace('/\s*[-–]\s*UPCindex.*$/i', '', $title); $empty['title'] = $title; } - // Recherche de l'image - if (preg_match('/]*src="([^"]+\.(?:jpg|jpeg|png|webp))"[^>]*alt="[^"]*product[^"]*"[^>]*>/i', $html, $m)) { - $empty['poster'] = trim($m[1]); - } elseif (preg_match('/]*property="og:image"[^>]*content="([^"]+)"/i', $html, $m)) { - $empty['poster'] = trim($m[1]); + // ✅ RÉCUPÉRATION DE L'IMAGE DEPUIS UPCINDEX (première image produit) + // Chercher la première image de produit (après le barcode) + if (preg_match_all('/]*itemprop="http:\/\/schema\.org\/image"[^>]*src="([^"]+)"/i', $html, $matches)) { + // Prendre la première image de produit (pas le barcode) + foreach ($matches[1] as $imgSrc) { + if (strpos($imgSrc, 'barcode.png') === false && strpos($imgSrc, 'upcindex.com') !== false) { + $empty['poster'] = 'https:' . $imgSrc; + break; + } + } + } + + // ✅ RÉCUPÉRATION DES MÉTADONNÉES PHYSIQUES + // Directeur + if (preg_match('/]*>director<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { + $empty['director'] = trim($m[1]); + } + + // Acteurs + if (preg_match_all('/]*>actor<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $actorsMatches)) { + $empty['actors'] = implode(', ', array_map('trim', $actorsMatches[1])); + } + + // Format + if (preg_match('/]*>format<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { + $format = trim($m[1]); + if (stripos($format, 'DVD') !== false) $empty['format'] = 'DVD'; + elseif (stripos($format, 'Blu-ray') !== false) $empty['format'] = 'Blu-ray'; + elseif (stripos($format, '4K') !== false) $empty['format'] = '4K Ultra HD'; + } + + // Aspect ratio + if (preg_match('/]*>aspect ratio<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { + $empty['aspect_ratio'] = trim($m[1]); + } + + // Nombre de disques + if (preg_match('/]*>number of discs<\/dt>\s*]*>(\d+)<\/dd>/is', $html, $m)) { + $empty['number_of_discs'] = (int)$m[1]; + } + + // Brand/Publisher + if (preg_match('/]*>brand<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { + $empty['publisher'] = trim($m[1]); + } + + // Region code + if (preg_match('/]*>region code<\/dt>\s*]*>([^<]+)<\/dd>/is', $html, $m)) { + $empty['description'] = 'Region ' . trim($m[1]); } // Nettoyage du titre @@ -473,14 +518,14 @@ function fetchFromMovieCovers($title, $year = '') { return $empty; } -// Dans la fonction fetchPhysicalByEan - Ligne ~780 +// ── AGGREGATEUR PHYSIQUE (VERSION MODIFIÉE) ── function fetchPhysicalByEan($ean, $pdo = null) { error_log("=== DEBUT fetchPhysicalByEan EAN=$ean ==="); $res = emptyPhysicalResult(); $title = ''; - // 1. GO-UPC.COM (Priorité 1) + // 1. GO-UPC.COM (Priorité 1 - pour titre et image) $goUpcData = fetchFromGoUpc($ean); error_log("GO-UPC -> title='" . ($goUpcData['title'] ?? '') . "' poster='" . ($goUpcData['poster'] ?? '') . "'"); if (!empty($goUpcData['title'])) { @@ -488,66 +533,45 @@ function fetchPhysicalByEan($ean, $pdo = null) { $res = $goUpcData; } - // 2. UPCINDEX.COM (Priorité 2 - si GO-UPC n'a rien donné) - if (empty($title)) { - $upcIndexData = fetchFromUpcIndex($ean); - error_log("UPCINDEX -> title='" . ($upcIndexData['title'] ?? '') . "' poster='" . ($upcIndexData['poster'] ?? '') . "'"); - if (!empty($upcIndexData['title'])) { - $title = $upcIndexData['title']; - $res = $upcIndexData; + // 2. UPCINDEX.COM (Priorité 2 - pour métadonnées physiques détaillées) + $upcIndexData = fetchFromUpcIndex($ean); + error_log("UPCINDEX -> title='" . ($upcIndexData['title'] ?? '') . "' director='" . ($upcIndexData['director'] ?? '') . "' actors='" . ($upcIndexData['actors'] ?? '') . "'"); + + if (!empty($upcIndexData['title']) && empty($title)) { + $title = $upcIndexData['title']; + } + + // Fusionner les données UPCINDEX (métadonnées physiques) + if (!empty($upcIndexData)) { + if (!empty($upcIndexData['director'])) $res['director'] = $upcIndexData['director']; + if (!empty($upcIndexData['actors'])) $res['actors'] = $upcIndexData['actors']; + if (!empty($upcIndexData['format'])) $res['format'] = $upcIndexData['format']; + if (!empty($upcIndexData['aspect_ratio'])) $res['aspect_ratio'] = $upcIndexData['aspect_ratio']; + if (!empty($upcIndexData['number_of_discs'])) $res['number_of_discs'] = $upcIndexData['number_of_discs']; + if (!empty($upcIndexData['publisher'])) $res['publisher'] = $upcIndexData['publisher']; + if (!empty($upcIndexData['description'])) $res['description'] = $upcIndexData['description']; + if (!empty($upcIndexData['year'])) $res['year'] = $upcIndexData['year']; + // ✅ GARDER L'IMAGE DE GO-UPC EN PRIORITÉ + if (empty($res['poster']) && !empty($upcIndexData['poster'])) { + $res['poster'] = $upcIndexData['poster']; } } - // 3. FNAC (Priorité 3 - si les deux précédents n'ont rien donné) + // 3. FNAC (Fallback si pas de titre) if (empty($title)) { $fnacData = fetchFromFnac($ean); - error_log("FNAC -> title='" . ($fnacData['title'] ?? '') . "' poster='" . ($fnacData['poster'] ?? '') . "'"); + error_log("FNAC -> title='" . ($fnacData['title'] ?? '') . "'"); if (!empty($fnacData['title'])) { $title = $fnacData['title']; - $res = $fnacData; + if (empty($res['title'])) $res = $fnacData; } } - // 4. Blu-ray.com par titre (si on a un titre) - $blurayData = []; - if (!empty($title)) { - $blurayData = fetchFromBlurayComByTitle($title); - error_log("BLURAY(byTitle) -> year='" . ($blurayData['year'] ?? '') . "' publisher='" . ($blurayData['publisher'] ?? '') . "'"); - } - - // 5. Fallback: Blu-ray.com par EAN (si aucun titre trouvé) - if (empty($blurayData) && empty($title)) { - $blurayData = fetchFromBlurayComByEan($ean); - $title = $blurayData['title'] ?? ''; - if (!empty($title)) { - $res = $blurayData; - error_log("BLURAY(byEan) -> title='$title'"); - } - } - - // Fusion des données Blu-ray.com - if (!empty($blurayData)) { - if (!empty($blurayData['length'])) $res['length'] = $blurayData['length']; - if (!empty($blurayData['number_of_discs'])) $res['number_of_discs'] = $blurayData['number_of_discs']; - if (!empty($blurayData['aspect_ratio'])) $res['aspect_ratio'] = $blurayData['aspect_ratio']; - if (!empty($blurayData['publisher'])) $res['publisher'] = $blurayData['publisher']; - if (!empty($blurayData['format'])) $res['format'] = $blurayData['format']; - // ⚠️ NE PAS ÉCRASER L'IMAGE DE GO-UPC - // if (!empty($blurayData['poster'])) $res['poster'] = $blurayData['poster']; - if (!empty($blurayData['year'])) $res['year'] = $blurayData['year']; - } - - // 6. MovieCovers (par titre) - Pour jaquette HD FR - if (!empty($title)) { + // 4. MovieCovers (pour jaquette HD FR si pas d'image) + if (!empty($title) && empty($res['poster'])) { $mc = fetchFromMovieCovers($title, $res['year'] ?? ''); error_log("MOVIECOVERS -> poster='" . ($mc['poster'] ?? '') . "'"); - // ⚠️ PRIORITÉ À L'IMAGE DE GO-UPC, SINON MOVIECOVERS - if (empty($res['poster']) && !empty($mc['poster'])) { - $res['poster'] = $mc['poster']; - } - if (!empty($mc['director'])) $res['director'] = $mc['director']; - if (!empty($mc['actors'])) $res['actors'] = $mc['actors']; - if (!empty($mc['description'])) $res['description'] = $mc['description']; + if (!empty($mc['poster'])) $res['poster'] = $mc['poster']; } error_log("=== FIN fetchPhysicalByEan -> title FINAL='" . ($res['title'] ?? '') . "' poster='" . ($res['poster'] ?? '') . "' ==="); @@ -660,37 +684,37 @@ switch ($action) { else { http_response_code(400); echo json_encode(["success" => false, "error" => "Aucun élément sélectionné."]); } break; - case 'add_item_by_ean': - $ean = preg_replace('/[^0-9]/', '', $data['ean'] ?? ''); - if (strlen($ean) < 8) { echo json_encode(["success" => false, "error" => "EAN invalide"]); exit; } - - $physicalData = fetchPhysicalByEan($ean, $pdo); - $rawTitle = $physicalData['title'] ?? ''; - - $tmdbData = fetchTmdbPosterAndSynopsis($rawTitle, $physicalData['year'] ?? '', $pdo); - - $finalTitle = !empty($tmdbData['title']) ? $tmdbData['title'] : $rawTitle; - - // ✅ PRIORITÉ À L'IMAGE DE GO-UPC/PHYSICAL DATA - $poster = !empty($physicalData['poster']) ? $physicalData['poster'] : - (($tmdbData['poster'] !== 'assets/img/default_physical_media.jpg') ? $tmdbData['poster'] : 'assets/img/default_physical_media.jpg'); - - $year = $tmdbData['year'] ?? $physicalData['year'] ?? ''; - $id = makeStableId('videotheque', $finalTitle, $year); - - $stmt = $pdo->prepare("INSERT INTO videotheque (id, title, year, poster, description, director, actors, ean_isbn13, format, length, publisher, number_of_discs, aspect_ratio) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), poster=IF(VALUES(poster)!='', VALUES(poster), poster), description=IF(VALUES(description)!='', VALUES(description), description), director=IF(VALUES(director)!='', VALUES(director), director), actors=IF(VALUES(actors)!='', VALUES(actors), actors)"); - $stmt->execute([ - $id, $finalTitle, $year, $poster, - $tmdbData['description'] ?? $physicalData['description'] ?? '', - $tmdbData['director'] ?: ($physicalData['director'] ?? ''), - $tmdbData['actors'] ?: ($physicalData['actors'] ?? ''), - $ean, $physicalData['format'] ?? detectFormat($rawTitle), - $tmdbData['length'] ?: ($physicalData['length'] ?? ''), - $physicalData['publisher'] ?? '', $physicalData['number_of_discs'] ?? 1, $physicalData['aspect_ratio'] ?? '' - ]); +case 'add_item_by_ean': + $ean = preg_replace('/[^0-9]/', '', $data['ean'] ?? ''); + if (strlen($ean) < 8) { echo json_encode(["success" => false, "error" => "EAN invalide"]); exit; } - echo json_encode(["success" => true, "title" => $finalTitle, "director" => $tmdbData['director'] ?: ($physicalData['director'] ?? ''), "year" => $year]); - break; + $physicalData = fetchPhysicalByEan($ean, $pdo); + $rawTitle = $physicalData['title'] ?? ''; + + $tmdbData = fetchTmdbPosterAndSynopsis($rawTitle, $physicalData['year'] ?? '', $pdo); + + $finalTitle = !empty($tmdbData['title']) ? $tmdbData['title'] : $rawTitle; + + // ✅ PRIORITÉ ABSOLUE À L'IMAGE DE GO-UPC/PHYSICAL + $poster = !empty($physicalData['poster']) ? $physicalData['poster'] : + (($tmdbData['poster'] !== 'assets/img/default_physical_media.jpg') ? $tmdbData['poster'] : 'assets/img/default_physical_media.jpg'); + + $year = $tmdbData['year'] ?? $physicalData['year'] ?? ''; + $id = makeStableId('videotheque', $finalTitle, $year); + + $stmt = $pdo->prepare("INSERT INTO videotheque (id, title, year, poster, description, director, actors, ean_isbn13, format, length, publisher, number_of_discs, aspect_ratio) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), poster=IF(VALUES(poster)!='', VALUES(poster), poster), description=IF(VALUES(description)!='', VALUES(description), description), director=IF(VALUES(director)!='', VALUES(director), director), actors=IF(VALUES(actors)!='', VALUES(actors), actors)"); + $stmt->execute([ + $id, $finalTitle, $year, $poster, + $tmdbData['description'] ?? $physicalData['description'] ?? '', + $physicalData['director'] ?: $tmdbData['director'], // ✅ Priorité aux données physiques + $physicalData['actors'] ?: $tmdbData['actors'], // ✅ Priorité aux données physiques + $ean, $physicalData['format'] ?? detectFormat($rawTitle), + $tmdbData['length'] ?: ($physicalData['length'] ?? ''), + $physicalData['publisher'] ?? '', $physicalData['number_of_discs'] ?? 1, $physicalData['aspect_ratio'] ?? '' + ]); + + echo json_encode(["success" => true, "title" => $finalTitle, "director" => $physicalData['director'] ?: $tmdbData['director'], "year" => $year]); + break; case 'import_batch': checkAuth($pdo);