From 2953d9e4fcf5e6c7d811bdb953bff152b073e342 Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 25 Jun 2026 09:53:20 +0200 Subject: [PATCH] Actualiser api.php --- api.php | 371 +++++++++++++++++++++++++------------------------------- 1 file changed, 164 insertions(+), 207 deletions(-) diff --git a/api.php b/api.php index 4f6fa6a..e5eb384 100644 --- a/api.php +++ b/api.php @@ -117,144 +117,109 @@ function extractYear($dateStr) { return ''; } -// ── Scraping Fnac.com ── -function fetchFnac($ean) { - if (empty($ean) || strlen($ean) < 8) return null; +// ── MovieCovers.com (jaquettes HD pour la vidéothèque) ── +function fetchMovieCovers($title, $year = '', $format = 'Blu-ray') { + 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 . ")"; + } - // Étape 1 : Recherche par EAN - $searchUrl = "https://www.fnac.com/SearchResult/ResultList.aspx?Search=" . urlencode($ean); $html = httpGet($searchUrl, 8, $ua); - if (!$html) { - error_log("Fnac: Échec recherche HTML pour EAN $ean"); + error_log("MovieCovers: Échec recherche pour '$title'"); return null; } - // Étape 2 : Extraire le lien vers la fiche produit - $productUrl = null; + $result = [ + 'poster' => '', + 'title' => '', + 'format' => $format, + ]; - // Chercher un lien vers une fiche produit (format /a12345678/...) - if (preg_match('/href=["\']([^"\']*\/a\d+\/[^"\'\s]+\.html)["\']/i', $html, $matches)) { - $productUrl = $matches[1]; - if (strpos($productUrl, 'http') !== 0) { - $productUrl = 'https://www.fnac.com' . $productUrl; + // 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; + } } } - if (!$productUrl) { - error_log("Fnac: Aucune fiche trouvée pour EAN $ean"); - return null; + // 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]; + } } - error_log("Fnac: Fiche trouvée - $productUrl"); - - // Étape 3 : Récupérer la fiche complète - $ficheHtml = httpGet($productUrl, 8, $ua); - if (!$ficheHtml) { - error_log("Fnac: Impossible de charger la fiche"); - return null; + // Extraire le titre depuis la page si disponible + if (preg_match('/]*>([^<]+) - MovieCovers/i', $html, $titleMatch)) { + $result['title'] = trim($titleMatch[1]); } - // Étape 4 : Extraire les données depuis le HTML - $result = [ - 'title' => '', - 'poster' => '', - 'publisher' => '', - 'format' => '', - 'length' => '', - 'aspect' => '', - 'discs' => '', - 'actors' => '', - 'description' => '', - ]; - - // Extraction du titre - if (preg_match('/]+property=["\']og:title["\'][^>]+content=["\']([^"\']+)["\']/i', $ficheHtml, $m)) { - $result['title'] = trim($m[1]); - } elseif (preg_match('/]*class=["\']ProductTitle[^"\']*["\'][^>]*>([^<]+)<\/h1>/i', $ficheHtml, $m)) { - $result['title'] = trim(strip_tags($m[1])); - } elseif (preg_match('/]*>([^<]+)<\/h1>/i', $ficheHtml, $m)) { - $result['title'] = trim(strip_tags($m[1])); - } - - // Extraction de l'affiche (plusieurs méthodes fallback) - if (preg_match('/]+property=["\']og:image["\'][^>]+content=["\']([^"\']+)["\']/i', $ficheHtml, $m)) { - $result['poster'] = $m[1]; - } elseif (preg_match('/]+rel=["\']image_src["\'][^>]+href=["\']([^"\']+)["\']/i', $ficheHtml, $m)) { - $result['poster'] = $m[1]; - } elseif (preg_match('/src=["\']([^"\']+(?:cdn\.fnac\.com|fnac\.com)[^"\']*\.(?:jpg|jpeg|png|webp))["\']/i', $ficheHtml, $m)) { - $result['poster'] = $m[1]; - } - - // Extraction des caractéristiques techniques (bloc "Fiche technique") - // On cherche les paires label/valeur dans le tableau de caractéristiques - if (preg_match('/]*class=["\'][^"\']*fiche-technique[^"\']*["\'][^>]*>(.*?)<\/div>/is', $ficheHtml, $bloc)) { - $techHtml = $bloc[1]; - } else { - $techHtml = $ficheHtml; - } - - // Éditeur / Distributeur - if (preg_match('/(?:Éditeur|Editeur|Distributeur|Studio|Label)\s*<\/[^>]+>\s*<[^>]+>([^<]+)/i', $techHtml, $m)) { - $result['publisher'] = trim(strip_tags($m[1])); - } elseif (preg_match('/(?:Éditeur|Editeur|Distributeur|Studio|Label)\s*[:<\/][^>]*>\s*([^<\n]+)/i', $ficheHtml, $m)) { - $result['publisher'] = trim(strip_tags($m[1])); - } - - // Durée - if (preg_match('/(?:Durée|Duree|Durata)\s*<\/[^>]+>\s*<[^>]+>(\d+)\s*(?:min|mn|h)/i', $techHtml, $m)) { - $result['length'] = trim($m[1]) . ' min'; - } elseif (preg_match('/(?:Durée|Duree)\s*[:<\/][^>]*>\s*(\d+)\s*(?:min|mn|h)/i', $ficheHtml, $m)) { - $result['length'] = trim($m[1]) . ' min'; - } - - // Nombre de disques - if (preg_match('/(?:Nombre\s*de\s*disques?|Nb\s*disques?|Disques?)\s*<\/[^>]+>\s*<[^>]+>(\d+)/i', $techHtml, $m)) { - $result['discs'] = trim($m[1]); - } elseif (preg_match('/(?:Nombre\s*de\s*disques?|Nb\s*disques?)\s*[:<\/][^>]*>\s*(\d+)/i', $ficheHtml, $m)) { - $result['discs'] = trim($m[1]); - } - - // Format image / Aspect ratio - if (preg_match('/(?:Format\s*(?:image|vidéo|video)|Ratio|Aspect\s*ratio)\s*<\/[^>]+>\s*<[^>]+>([0-9.]+\s*[:\.]\s*[0-9.]+)/i', $techHtml, $m)) { - $result['aspect'] = trim($m[1]); - } - - // Acteurs / Casting - if (preg_match('/(?:Acteurs?|Casting|Avec)\s*<\/[^>]+>\s*<[^>]+>([^<]+)/i', $techHtml, $m)) { - $result['actors'] = trim(strip_tags($m[1])); - } elseif (preg_match('/(?:Avec|Acteurs?)\s*[:<\/][^>]*>\s*([^<\n]+)/i', $ficheHtml, $m)) { - $result['actors'] = trim(strip_tags($m[1])); - } - - // Description / Synopsis - if (preg_match('/]*class=["\'][^"\']*product-description[^"\']*["\'][^>]*>(.*?)<\/div>/is', $ficheHtml, $m)) { - $result['description'] = trim(strip_tags($m[1])); - } elseif (preg_match('/]+property=["\']og:description["\'][^>]+content=["\']([^"\']+)["\']/i', $ficheHtml, $m)) { - $result['description'] = trim($m[1]); - } - - // Format (détection depuis le titre ou la fiche) - $formatText = $result['title'] . ' ' . $ficheHtml; - if (preg_match('/(4K\s*Ultra\s*HD|Ultra\s*HD|4K|Blu[\s-]?Ray|DVD|Coffret)/i', $formatText, $m)) { - $fmt = strtoupper(trim($m[1])); - if (strpos($fmt, '4K') !== false || strpos($fmt, 'ULTRA') !== false) $result['format'] = '4K Ultra HD'; - elseif (strpos($fmt, 'BLU') !== false) $result['format'] = 'Blu-ray'; - elseif (strpos($fmt, 'DVD') !== false) $result['format'] = 'DVD'; - elseif (strpos($fmt, 'COFFRET') !== false) $result['format'] = 'Coffret'; - } - - // Nettoyage final - foreach ($result as $k => $v) { - $result[$k] = trim(html_entity_decode($v, ENT_QUOTES | ENT_HTML5, 'UTF-8')); - } - - return (!empty($result['title']) || !empty($result['poster'])) ? $result : null; + return (!empty($result['poster'])) ? $result : null; } -// ── API TMDB (SANS CACHE - TITRE FRANÇAIS) ── +// 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 + $formatMap = [ + '4k ultra hd' => '4k', + '4k' => '4k', + 'blu-ray' => 'bluray', + 'bluray' => 'bluray', + 'dvd' => 'dvd', + ]; + + $mcFormat = $formatMap[strtolower($format)] ?? 'bluray'; + + // URL directe vers la page du cover + $directUrl = "https://moviecovers.com/{$mcFormat}/{$cleanTitle}"; + $html = httpGet($directUrl, 8, $ua); + + if (!$html) { + // Fallback sur la recherche + return fetchMovieCovers($title, '', $format); + } + + $result = [ + 'poster' => '', + 'title' => '', + '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]; + } + + return (!empty($result['poster'])) ? $result : null; +} + +// ── API TMDB (uniquement pour les critiques) ── function fetchTMDBFull($title, $year, $apiKey, $pdo) { if (empty($apiKey) || empty($title)) return null; $cleanTitle = cleanTitle($title); @@ -393,6 +358,7 @@ switch ($action) { case 'search_ean_full': $ean = $_GET['ean'] ?? ''; + $type = $_GET['type'] ?? 'videotheque'; if (!$ean) { echo json_encode(['error' => 'EAN manquant']); exit; } $result = [ 'ean' => $ean, 'title' => '', 'director' => '', 'year' => '', @@ -400,35 +366,56 @@ switch ($action) { 'length' => '', 'number_of_discs' => 1, 'aspect_ratio' => '', 'actors' => '' ]; - // Étape 1 : Scraping Fnac - $fnacData = fetchFnac($ean); - $titleForTmdb = ''; - if (!empty($fnacData)) { - if (!empty($fnacData['title'])) $result['title'] = $fnacData['title']; - if (!empty($fnacData['poster'])) $result['poster'] = $fnacData['poster']; - if (!empty($fnacData['publisher'])) $result['publisher'] = $fnacData['publisher']; - if (!empty($fnacData['format'])) $result['format'] = $fnacData['format']; - if (!empty($fnacData['length'])) $result['length'] = $fnacData['length']; - if (!empty($fnacData['aspect'])) $result['aspect_ratio'] = $fnacData['aspect']; - if (!empty($fnacData['discs'])) $result['number_of_discs'] = (int)$fnacData['discs']; - if (!empty($fnacData['actors'])) $result['actors'] = $fnacData['actors']; - - $titleForTmdb = cleanTitle($fnacData['title'] ?? ''); - } - - // Étape 2 : TMDB pour métadonnées film (réalisateur, vraie affiche, année) + // 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 $tmdbKey = getTmdbApiKey($pdo); - if ($tmdbKey && !empty($titleForTmdb)) { - $tmdbData = fetchTMDBFull($titleForTmdb, '', $tmdbKey, $pdo); - if ($tmdbData) { - if (!empty($tmdbData['title'])) $result['title'] = $tmdbData['title']; - if (!empty($tmdbData['year'])) $result['year'] = $tmdbData['year']; - if (!empty($tmdbData['director'])) $result['director'] = $tmdbData['director']; - if (!empty($tmdbData['length'])) $result['length'] = $tmdbData['length']; - if (!empty($tmdbData['cast'])) $result['actors'] = implode(', ', $tmdbData['cast']); - if (!empty($tmdbData['poster'])) $result['poster'] = $tmdbData['poster']; // TMDB prioritaire + $titleForSearch = ''; + + if ($type === 'critique' && $tmdbKey) { + // Pour les critiques, on cherche d'abord sur TMDB + $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) : []; + + if (!empty($searchData['movie_results'][0])) { + $titleForSearch = $searchData['movie_results'][0]['title']; + $result['title'] = $titleForSearch; + if (!empty($searchData['movie_results'][0]['release_date'])) { + $result['year'] = substr($searchData['movie_results'][0]['release_date'], 0, 4); + } } } + + // 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']); + exit; + } + + // Récupération jaquette via MovieCovers (pour vidéothèque) ou TMDB (pour critiques) + if ($type === 'videotheque') { + $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']; + $result['format'] = $format; + } + } else { + // Critiques : TMDB complet + if ($tmdbKey) { + $tmdbData = fetchTMDBFull($titleForSearch, $result['year'], $tmdbKey, $pdo); + if ($tmdbData) { + if (!empty($tmdbData['title'])) $result['title'] = $tmdbData['title']; + if (!empty($tmdbData['year'])) $result['year'] = $tmdbData['year']; + if (!empty($tmdbData['director'])) $result['director'] = $tmdbData['director']; + if (!empty($tmdbData['poster'])) $result['poster'] = $tmdbData['poster']; + if (!empty($tmdbData['length'])) $result['length'] = $tmdbData['length']; + if (!empty($tmdbData['cast'])) $result['actors'] = implode(', ', $tmdbData['cast']); + } + } + } + echo json_encode(['success' => true, 'data' => $result]); break; @@ -437,7 +424,8 @@ switch ($action) { $type = $data['type'] ?? 'critique'; $id = !empty($data['id']) ? $data['id'] : makeStableId($type, $data['title'] ?? '', $data['year'] ?? '0000'); - if (empty($data['director']) || empty($data['poster'])) { + // TMDB uniquement pour les critiques + if ($type === 'critique' && (empty($data['director']) || empty($data['poster']))) { $tmdbData = fetchTMDBFull($data['title'] ?? '', $data['year'] ?? '', getTmdbApiKey($pdo), $pdo); if ($tmdbData) { if (empty($data['director'])) $data['director'] = $tmdbData['director']; @@ -453,6 +441,15 @@ 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 + 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']; + } + } + $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description, actors) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=IF(VALUES(director)!='', VALUES(director), director), poster=IF(VALUES(poster)!='', VALUES(poster), poster), format=IF(VALUES(format)!='', VALUES(format), format), length=IF(VALUES(length)!='', VALUES(length), length), publisher=IF(VALUES(publisher)!='', VALUES(publisher), publisher), ean_isbn13=IF(VALUES(ean_isbn13)!='', VALUES(ean_isbn13), ean_isbn13), number_of_discs=IF(VALUES(number_of_discs)!=1, VALUES(number_of_discs), number_of_discs), aspect_ratio=IF(VALUES(aspect_ratio)!='', VALUES(aspect_ratio), aspect_ratio), description=IF(VALUES(description)!='', VALUES(description), description), actors=IF(VALUES(actors)!='', VALUES(actors), actors)"; $stmt = $pdo->prepare($sql); $stmt->execute([$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $data['poster'] ?? '', $data['format'] ?? '', $data['length'] ?? '', $data['publisher'] ?? '', $data['ean_isbn13'] ?? '', $data['number_of_discs'] ?? 1, $data['aspect_ratio'] ?? '', $data['description'] ?? '', $data['actors'] ?? '']); @@ -494,6 +491,7 @@ switch ($action) { $id = makeStableId($type, $title, $year); if ($type === 'videotheque') { + // ── VIDÉOTHÈQUE : MovieCovers pour jaquette HD, PAS de TMDB ── $csvActors = $rowData['ensemble'] ?? $rowData['creators'] ?? ''; $actors = ''; if (!empty($csvActors)) { @@ -525,66 +523,21 @@ switch ($action) { $poster = $rowData['poster'] ?? ''; $director = ''; - // Enrichissement via Fnac si on a un EAN - if (!empty($ean)) { - $fnacData = fetchFnac($ean); - if (!empty($fnacData)) { - if ((empty($title) || $title === 'Sans titre') && !empty($fnacData['title'])) { - $title = cleanTitle($fnacData['title']); + // 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']; } - if (empty($publisher) && !empty($fnacData['publisher'])) { - $publisher = $fnacData['publisher']; - } - if (empty($format) && !empty($fnacData['format'])) { - $format = $fnacData['format']; - } - if (empty($length) && !empty($fnacData['length'])) { - $length = $fnacData['length']; - } - if (empty($aspect) && !empty($fnacData['aspect'])) { - $aspect = $fnacData['aspect']; - } - if ($discs === 1 && !empty($fnacData['discs'])) { - $discs = (int)$fnacData['discs']; - } - if (empty($actors) && !empty($fnacData['actors'])) { - $actors = $fnacData['actors']; - } - if (empty($poster) && !empty($fnacData['poster'])) { - $poster = $fnacData['poster']; - } - if (empty($description) && !empty($fnacData['description'])) { - $description = $fnacData['description']; + if (!empty($mcData['title']) && ($title === 'Sans titre' || empty($title))) { + $title = $mcData['title']; } } } - // Enrichissement via TMDB - if ($tmdbApiKey && !empty($title)) { - $tmdbTitle = $title; - $tmdbTitle = preg_replace('/\s*[\[\(].*?[\]\)]\s*/', '', $tmdbTitle); - $tmdbTitle = preg_replace('/\s*-\s*(Édition|Edition|Collector|Simple|Spéciale|Digibook|Ultimate|Intégrale|Combo|SteelBook|Boîtier|Coffret).*$/i', '', $tmdbTitle); - $tmdbTitle = preg_replace('/\s*(Blu-ray|Bluray|DVD|4K|Ultra HD|Combo|VHS|BDRip|\[.*\]).*$/i', '', $tmdbTitle); - $tmdbTitle = preg_replace('/\s*(Coffret|Trilogie|Quadrilogie|Collection|Anthologie).*$/i', '', $tmdbTitle); - $tmdbTitle = preg_split('/\s*(\/|\+|:)\s*/', $tmdbTitle)[0]; - $tmdbTitle = explode(' - ', $tmdbTitle)[0]; - $tmdbTitle = trim($tmdbTitle); - - $tmdbData = fetchTMDBFull($tmdbTitle, $year, $tmdbApiKey, $pdo); - if (!$tmdbData && $tmdbTitle !== $title) { - $tmdbData = fetchTMDBFull($title, $year, $tmdbApiKey, $pdo); - } - - if ($tmdbData) { - if (!empty($tmdbData['title'])) $title = $tmdbData['title']; - if (empty($director)) $director = $tmdbData['director'] ?? ''; - if (empty($year) && !empty($tmdbData['year'])) $year = $tmdbData['year']; - if (empty($length) && !empty($tmdbData['length'])) $length = $tmdbData['length']; - if (!empty($tmdbData['overview'])) $description = $tmdbData['overview']; - if (!empty($tmdbData['cast'])) $actors = implode(', ', $tmdbData['cast']); - if (!empty($tmdbData['poster'])) $poster = $tmdbData['poster']; // TMDB prioritaire - } - } + // PAS D'APPEL TMDB POUR LA 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) @@ -604,6 +557,7 @@ switch ($action) { $stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $description, $actors]); } else { + // ── CRITIQUES : TMDB complet ── $ratingRaw = $rowData['Rating'] ?? $rowData['rating'] ?? ''; $rating = ($ratingRaw !== '' && $ratingRaw !== null) ? (float)$ratingRaw : null; $review = $rowData['Review'] ?? $rowData['review'] ?? ''; @@ -648,12 +602,15 @@ switch ($action) { } break; - case 'debug_fnac': - $ean = $_GET['ean'] ?? ''; - if (!$ean) { echo json_encode(['error' => 'EAN manquant']); exit; } + case 'debug_moviecovers': + $title = $_GET['title'] ?? ''; + $year = $_GET['year'] ?? ''; + $format = $_GET['format'] ?? 'Blu-ray'; - $result = ['ean' => $ean]; - $data = fetchFnac($ean); + if (!$title) { echo json_encode(['error' => 'Titre manquant']); exit; } + + $result = ['title' => $title, 'year' => $year, 'format' => $format]; + $data = fetchMovieCovers($title, $year, $format); $result['data'] = $data; $result['status'] = $data ? 'OK' : 'AUCUN_RÉSULTAT';