Actualiser api.php

This commit is contained in:
2026-06-26 14:00:03 +02:00
parent 60e0903c4f
commit 61352a6aa2
+125 -314
View File
@@ -16,15 +16,12 @@ try {
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]); ]);
$pdo->exec("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL)"); $pdo->exec("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL)");
$pdo->exec("CREATE TABLE IF NOT EXISTS config (key_name VARCHAR(50) PRIMARY KEY, key_value TEXT NOT NULL)"); $pdo->exec("CREATE TABLE IF NOT EXISTS config (key_name VARCHAR(50) PRIMARY KEY, key_value TEXT NOT NULL)");
$pdo->exec("CREATE TABLE IF NOT EXISTS critiques (id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), poster TEXT, rating DECIMAL(3,1) DEFAULT 3.0, review TEXT, streaming VARCHAR(255))"); $pdo->exec("CREATE TABLE IF NOT EXISTS critiques (id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), poster TEXT, rating DECIMAL(3,1) DEFAULT 3.0, review TEXT, streaming VARCHAR(255))");
try { $pdo->exec("ALTER TABLE critiques MODIFY COLUMN rating DECIMAL(3,1) DEFAULT 3.0"); } catch (\Exception $e) {} try { $pdo->exec("ALTER TABLE critiques MODIFY COLUMN rating DECIMAL(3,1) DEFAULT 3.0"); } catch (\Exception $e) {}
$pdo->exec("CREATE TABLE IF NOT EXISTS videotheque (id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), poster TEXT, format VARCHAR(50), length VARCHAR(50), publisher VARCHAR(255), ean_isbn13 VARCHAR(50), number_of_discs INT DEFAULT 1, aspect_ratio VARCHAR(50), description TEXT, actors TEXT)"); $pdo->exec("CREATE TABLE IF NOT EXISTS videotheque (id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), poster TEXT, format VARCHAR(50), length VARCHAR(50), publisher VARCHAR(255), ean_isbn13 VARCHAR(50), number_of_discs INT DEFAULT 1, aspect_ratio VARCHAR(50), description TEXT, actors TEXT)");
try { $pdo->exec("ALTER TABLE videotheque ADD COLUMN actors TEXT AFTER description"); } catch (\Exception $e) {} try { $pdo->exec("ALTER TABLE videotheque ADD COLUMN actors TEXT AFTER description"); } catch (\Exception $e) {}
} catch (\PDOException $e) { echo json_encode(["error" => "Erreur BDD : " . $e->getMessage()]); exit; } } catch (\PDOException $e) { echo json_encode(["error" => "Erreur BDD : " . $e->getMessage()]); exit; }
// ── FONCTIONS UTILITAIRES ── // ── FONCTIONS UTILITAIRES ──
@@ -50,7 +47,7 @@ function encryptData($data) {
function decryptData($str) { function decryptData($str) {
$decoded = base64_decode($str); $decoded = base64_decode($str);
if (strpos($decoded, '::') === false) return null; if ($decoded === false || strpos($decoded, '::') === false) return null;
list($enc, $iv) = explode('::', $decoded, 2); list($enc, $iv) = explode('::', $decoded, 2);
return openssl_decrypt($enc, 'AES-256-CBC', hash('sha256', ENCRYPTION_KEY, true), OPENSSL_RAW_DATA, substr($iv, 0, 16)); return openssl_decrypt($enc, 'AES-256-CBC', hash('sha256', ENCRYPTION_KEY, true), OPENSSL_RAW_DATA, substr($iv, 0, 16));
} }
@@ -69,9 +66,36 @@ function getFanartApiKey($pdo) {
return $row ? decryptData($row['key_value']) : null; return $row ? decryptData($row['key_value']) : null;
} }
function httpGet($url, $timeout = 10, $ua = null) { function httpGet($url, $timeout = 5, $ua = null) {
if (!$ua) $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'; if (!$ua) $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36';
if (!function_exists('curl_init')) {
$ctx = stream_context_create(['http' => ['timeout' => $timeout, 'user_agent' => $ua]]);
$res = @file_get_contents($url, false, $ctx);
return $res ?: null;
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => $ua,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_REFERER => 'https://www.cinemapassion.com/',
CURLOPT_HTTPHEADER => [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: fr-FR,fr;q=0.8',
],
]);
$res = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ($code === 200 && is_string($res) && strlen($res) > 0) ? $res : null;
}
function httpPost($url, $postData, $timeout = 10) {
$ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36';
if (!function_exists('curl_init')) return null;
$ch = curl_init($url); $ch = curl_init($url);
curl_setopt_array($ch, [ curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
@@ -80,20 +104,20 @@ function httpGet($url, $timeout = 10, $ua = null) {
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => $ua, CURLOPT_USERAGENT => $ua,
CURLOPT_FOLLOWLOCATION => true, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_REFERER => 'https://www.cinemapassion.com/', // Crucial pour éviter le blocage CURLOPT_POST => true,
CURLOPT_POSTFIELDS => is_array($postData) ? http_build_query($postData) : $postData,
CURLOPT_REFERER => 'https://www.cinemapassion.com/',
CURLOPT_HTTPHEADER => [ CURLOPT_HTTPHEADER => [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Content-Type: application/x-www-form-urlencoded',
'Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Connection: keep-alive', 'Accept-Language: fr-FR,fr;q=0.8',
'Upgrade-Insecure-Requests: 1' 'Origin: https://www.cinemapassion.com'
], ],
]); ]);
$res = curl_exec($ch); $res = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); curl_close($ch);
return ($code === 200 && is_string($res) && strlen($res) > 0) ? $res : null;
// Si le code est 403, le site vous a banni, essayez de ralentir les requêtes
return ($code === 200) ? $res : null;
} }
function cleanTitle($title) { function cleanTitle($title) {
@@ -113,12 +137,7 @@ function detectFormat($title, $desc = '') {
return 'Blu-ray'; return 'Blu-ray';
} }
function extractYear($dateStr) { // ── FONCTION PRINCIPALE : CINEMAPASSION.COM ──
if (preg_match('/(\d{4})/', $dateStr, $m)) return $m[1];
return '';
}
// ── FONCTION POUR RÉCUPÉRER LES IMAGES DEPUIS CINEMAPASSION.COM ──
function fetchCinemaPassion($title, $year = '', $ean = '', $pdo = null) { function fetchCinemaPassion($title, $year = '', $ean = '', $pdo = null) {
$defaultPoster = 'assets/img/default_physical_media.jpg'; $defaultPoster = 'assets/img/default_physical_media.jpg';
$cleanTitle = cleanTitle($title); $cleanTitle = cleanTitle($title);
@@ -127,151 +146,78 @@ function fetchCinemaPassion($title, $year = '', $ean = '', $pdo = null) {
return ['poster' => $defaultPoster, 'title' => '', 'format' => 'Blu-ray']; return ['poster' => $defaultPoster, 'title' => '', 'format' => 'Blu-ray'];
} }
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'; // ÉTAPE 1 : Recherche POST sur /moteur2.php
$searchRes = httpPost('https://www.cinemapassion.com/moteur2.php', ['recherche' => $cleanTitle]);
// ── ÉTAPE 1 : Recherche via POST sur /moteur2.php ── if ($searchRes) {
$searchUrl = "https://www.cinemapassion.com/moteur2.php"; // ÉTAPE 2 : Extraire le lien vers la page du film
// Pattern : href='../film/Saw-3814.php' ou href='film/Saw-3814.php'
if (preg_match('/href=["\']?(?:\.\.\/)?film\/([^"\'\s]+)-(\d+)\.php["\']?/i', $searchRes, $matches)) {
$filmName = $matches[1];
$filmId = $matches[2];
$ch = curl_init($searchUrl); // ÉTAPE 3 : Essayer plusieurs pages pour trouver l'image
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['recherche' => $cleanTitle]),
CURLOPT_REFERER => 'https://www.cinemapassion.com/',
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: fr-FR,fr;q=0.8',
'Origin: https://www.cinemapassion.com'
],
]);
$searchRes = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// ✅ CORRECTION : Vérifier que $searchRes n'est pas null ou false
$html = ($code === 200 && $searchRes && is_string($searchRes)) ? $searchRes : null;
if ($html) {
// ── ÉTAPE 2 : Extraire le lien vers la page du film ──
if (preg_match('/href=["\']([^"\']*film\/[^"\'\/]+-\d+\.php)["\']/i', $html, $matches)) {
$filmPath = $matches[1];
$filmPath = str_replace('../', '', $filmPath);
if (strpos($filmPath, '/') !== 0) {
$filmUrl = 'https://www.cinemapassion.com/' . $filmPath;
} else {
$filmUrl = 'https://www.cinemapassion.com' . $filmPath;
}
if (preg_match('/film\/([^\/]+)-(\d+)\.php/i', $filmUrl, $filmMatches)) {
$filmName = $filmMatches[1];
$filmId = $filmMatches[2];
// ── ÉTAPE 3 : Essayer plusieurs pages pour trouver l'image ──
$pagesToTry = [ $pagesToTry = [
"https://www.cinemapassion.com/jaquette-dvd-{$filmName}-{$filmId}.php", "https://www.cinemapassion.com/jaquette-dvd-{$filmName}-{$filmId}.php",
"https://www.cinemapassion.com/jaquette-blu-ray-{$filmName}-{$filmId}.php", "https://www.cinemapassion.com/jaquette-blu-ray-{$filmName}-{$filmId}.php",
$filmUrl, "https://www.cinemapassion.com/film/{$filmName}-{$filmId}.php",
"https://www.cinemapassion.com/sticker-dvd-{$filmName}-{$filmId}.php", "https://www.cinemapassion.com/sticker-dvd-{$filmName}-{$filmId}.php",
]; ];
foreach ($pagesToTry as $pageUrl) { foreach ($pagesToTry as $pageUrl) {
$pageRes = httpGet($pageUrl, 10, $userAgent); $pageRes = httpGet($pageUrl, 10);
// ✅ CORRECTION : Vérifier que $pageRes est une string valide if ($pageRes) {
if ($pageRes && is_string($pageRes) && strlen($pageRes) > 0) { // Pattern : src='http://www.cinemapassion.com/covers_temp/covers3/Saw-13005811062007.jpg'
// Pattern pour l'image if (preg_match('/src=["\']?(https?:\/\/(?:www\.)?cinemapassion\.com\/covers_temp\/covers\d*\/[^"\'\s>]+\.jpg)["\']?/i', $pageRes, $imgMatches)) {
if (preg_match('/src=["\']?(https?:\/\/[^"\'\s>]*cinemapassion\.com[^"\'\s>]*covers[^"\'\s>]*\.jpg)["\']?/i', $pageRes, $imgMatches)) {
$posterUrl = $imgMatches[1]; $posterUrl = $imgMatches[1];
$posterUrl = str_replace('http://', 'https://', $posterUrl); $posterUrl = str_replace('http://', 'https://', $posterUrl);
error_log("CinemaPassion OK: '{$cleanTitle}' → {$posterUrl}");
error_log("CinemaPassion: Image trouvée pour '{$cleanTitle}' → {$posterUrl}"); return ['poster' => $posterUrl, 'title' => $cleanTitle, 'format' => 'Blu-ray'];
return [
'poster' => $posterUrl,
'title' => $cleanTitle,
'format' => 'Blu-ray'
];
} }
// Fallback : image dans lesaffiches/
if (preg_match('/src=["\']?(https?:\/\/(?:www\.)?cinemapassion\.com\/lesaffiches\/[^"\'\s>]+\.jpg)["\']?/i', $pageRes, $imgMatches)) {
$posterUrl = $imgMatches[1];
$posterUrl = str_replace('http://', 'https://', $posterUrl);
error_log("CinemaPassion OK (affiche): '{$cleanTitle}' → {$posterUrl}");
return ['poster' => $posterUrl, 'title' => $cleanTitle, 'format' => 'Blu-ray'];
} }
} }
} }
} }
// ── FALLBACK : Chercher directement une image dans les résultats ── // Fallback : chercher directement une image covers_temp dans les résultats
if (preg_match('/src=["\']?(https?:\/\/[^"\'\s>]*cinemapassion\.com[^"\'\s>]*covers[^"\'\s>]*\.jpg)["\']?/i', $html, $imgMatches)) { if (preg_match('/src=["\']?(https?:\/\/(?:www\.)?cinemapassion\.com\/covers_temp\/covers\d*\/[^"\'\s>]+\.jpg)["\']?/i', $searchRes, $imgMatches)) {
$posterUrl = str_replace('http://', 'https://', $imgMatches[1]); $posterUrl = str_replace('http://', 'https://', $imgMatches[1]);
error_log("CinemaPassion: Image trouvée (fallback) pour '{$cleanTitle}' → {$posterUrl}"); error_log("CinemaPassion OK (direct): '{$cleanTitle}' → {$posterUrl}");
return [ return ['poster' => $posterUrl, 'title' => $cleanTitle, 'format' => 'Blu-ray'];
'poster' => $posterUrl,
'title' => $cleanTitle,
'format' => 'Blu-ray'
];
} }
} }
error_log("CinemaPassion: Image NON trouvée pour '{$cleanTitle}'"); error_log("CinemaPassion KO: Image NON trouvée pour '{$cleanTitle}'");
return ['poster' => $defaultPoster, 'title' => $cleanTitle, 'format' => 'Blu-ray']; return ['poster' => $defaultPoster, 'title' => $cleanTitle, 'format' => 'Blu-ray'];
} }
// ── ROUTEUR PRINCIPAL ──
// Fonction pour vérifier si une URL existe
function urlExists($url, $timeout = 3) {
if (!function_exists('curl_init')) {
$ctx = stream_context_create(['http' => ['timeout' => $timeout, 'method' => 'HEAD']]);
$result = @get_headers($url, 0, $ctx);
return ($result && strpos($result[0], '200') !== 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);
}
// ── API TMDB (uniquement pour les critiques) ── // ── API TMDB (uniquement pour les critiques) ──
function fetchTMDBFull($title, $year, $apiKey, $pdo) { function fetchTMDBFull($title, $year, $apiKey, $pdo) {
if (empty($apiKey) || empty($title)) return null; if (empty($apiKey) || empty($title)) return null;
$cleanTitle = cleanTitle($title); $cleanTitle = cleanTitle($title);
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($cleanTitle) . "&year={$year}&language=fr-FR"; $searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($cleanTitle) . "&year={$year}&language=fr-FR";
$searchRes = httpGet($searchUrl, 5); $searchRes = httpGet($searchUrl, 5);
$searchData = $searchRes ? json_decode($searchRes, true) : []; $searchData = $searchRes ? json_decode($searchRes, true) : [];
if (empty($searchData['results'])) { if (empty($searchData['results'])) {
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($cleanTitle) . "&language=fr-FR"; $searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($cleanTitle) . "&language=fr-FR";
$searchRes = httpGet($searchUrl, 5); $searchRes = httpGet($searchUrl, 5);
$searchData = $searchRes ? json_decode($searchRes, true) : []; $searchData = $searchRes ? json_decode($searchRes, true) : [];
} }
if (empty($searchData['results'])) return null; if (empty($searchData['results'])) return null;
$movieId = $searchData['results'][0]['id']; $movieId = $searchData['results'][0]['id'];
$detailsUrl = "https://api.themoviedb.org/3/movie/{$movieId}?api_key={$apiKey}&append_to_response=credits,watch/providers,translations&language=fr-FR"; $detailsUrl = "https://api.themoviedb.org/3/movie/{$movieId}?api_key={$apiKey}&append_to_response=credits,watch/providers,translations&language=fr-FR";
$detailsRes = httpGet($detailsUrl, 5); $detailsRes = httpGet($detailsUrl, 5);
if (!$detailsRes) return null; if (!$detailsRes) return null;
$details = json_decode($detailsRes, true); $details = json_decode($detailsRes, true);
$frenchTitle = $details['title'] ?? ''; $frenchTitle = $details['title'] ?? '';
if (!empty($details['translations']['translations'])) { if (!empty($details['translations']['translations'])) {
foreach ($details['translations']['translations'] as $translation) { foreach ($details['translations']['translations'] as $translation) {
if ($translation['iso_3166_1'] === 'FR' && !empty($translation['data']['title'])) { if ($translation['iso_3166_1'] === 'FR' && !empty($translation['data']['title'])) {
@@ -280,7 +226,6 @@ function fetchTMDBFull($title, $year, $apiKey, $pdo) {
} }
} }
} }
$director = ''; $director = '';
if (!empty($details['credits']['crew'])) { if (!empty($details['credits']['crew'])) {
$directorsList = []; $directorsList = [];
@@ -289,15 +234,11 @@ function fetchTMDBFull($title, $year, $apiKey, $pdo) {
} }
$director = implode(', ', $directorsList); $director = implode(', ', $directorsList);
} }
$cast = []; $cast = [];
if (!empty($details['credits']['cast'])) { if (!empty($details['credits']['cast'])) {
$topCast = array_slice($details['credits']['cast'], 0, 4); $topCast = array_slice($details['credits']['cast'], 0, 4);
foreach ($topCast as $actor) $cast[] = $actor['name']; foreach ($topCast as $actor) $cast[] = $actor['name'];
} }
$overview = $details['overview'] ?? '';
$streaming = ''; $streaming = '';
$frProviders = $details['watch/providers']['results']['FR'] ?? []; $frProviders = $details['watch/providers']['results']['FR'] ?? [];
$platforms = []; $platforms = [];
@@ -307,19 +248,16 @@ function fetchTMDBFull($title, $year, $apiKey, $pdo) {
if (!empty($frProviders['buy'])) { foreach ($frProviders['buy'] as $p) $platforms[] = $p['provider_name'] . ' (achat)'; } if (!empty($frProviders['buy'])) { foreach ($frProviders['buy'] as $p) $platforms[] = $p['provider_name'] . ' (achat)'; }
} }
if (!empty($platforms)) $streaming = implode(', ', array_unique($platforms)); if (!empty($platforms)) $streaming = implode(', ', array_unique($platforms));
return [
$result = [
'title' => $frenchTitle, 'title' => $frenchTitle,
'year' => !empty($details['release_date']) ? substr($details['release_date'], 0, 4) : '', 'year' => !empty($details['release_date']) ? substr($details['release_date'], 0, 4) : '',
'director' => $director, 'director' => $director,
'poster' => !empty($details['poster_path']) ? "https://image.tmdb.org/t/p/w500" . $details['poster_path'] : '', 'poster' => !empty($details['poster_path']) ? "https://image.tmdb.org/t/p/w500" . $details['poster_path'] : '',
'length' => !empty($details['runtime']) ? $details['runtime'] . ' min' : '', 'length' => !empty($details['runtime']) ? $details['runtime'] . ' min' : '',
'streaming' => $streaming, 'streaming' => $streaming,
'overview' => $overview, 'overview' => $details['overview'] ?? '',
'cast' => $cast 'cast' => $cast
]; ];
return $result;
} }
// ── ROUTEUR PRINCIPAL ── // ── ROUTEUR PRINCIPAL ──
@@ -389,7 +327,6 @@ case 'get_config_keys':
ORDER BY id DESC ORDER BY id DESC
"; ";
$result = $pdo->query($sql)->fetchAll(); $result = $pdo->query($sql)->fetchAll();
foreach ($result as $row) { foreach ($result as $row) {
if ($row['rating'] !== null) { if ($row['rating'] !== null) {
$ratingVal = (float)$row['rating']; $ratingVal = (float)$row['rating'];
@@ -397,67 +334,9 @@ case 'get_config_keys':
} }
} }
unset($row); unset($row);
echo json_encode($result); echo json_encode($result);
break; break;
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' => '',
'poster' => '', 'publisher' => '', 'format' => '',
'length' => '', 'number_of_discs' => 1, 'aspect_ratio' => '', 'actors' => ''
];
$tmdbKey = getTmdbApiKey($pdo);
$titleForSearch = '';
if ($tmdbKey) {
$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);
}
}
}
if (empty($titleForSearch)) {
echo json_encode(['success' => true, 'data' => $result, 'warning' => 'Titre non trouvé']);
exit;
}
if ($type === 'videotheque') {
$format = $result['format'] ?: 'Blu-ray';
$fanartData = fetchFanartTv($titleForSearch, $result['year'], $format, $pdo);
if (!empty($fanartData)) {
if (!empty($fanartData['poster'])) $result['poster'] = $fanartData['poster'];
if (!empty($fanartData['title'])) $result['title'] = $fanartData['title'];
$result['format'] = $format;
}
} else {
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;
case 'save_film': case 'save_film':
checkAuth($pdo); checkAuth($pdo);
$type = $data['type'] ?? 'critique'; $type = $data['type'] ?? 'critique';
@@ -468,7 +347,6 @@ case 'get_config_keys':
if ($tmdbData) { if ($tmdbData) {
if (empty($data['director'])) $data['director'] = $tmdbData['director']; if (empty($data['director'])) $data['director'] = $tmdbData['director'];
if (empty($data['poster'])) $data['poster'] = $tmdbData['poster']; if (empty($data['poster'])) $data['poster'] = $tmdbData['poster'];
if (empty($data['length']) && !empty($tmdbData['length'])) $data['length'] = $tmdbData['length'];
} }
} }
@@ -480,13 +358,11 @@ case 'get_config_keys':
$stmt->execute([$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $data['poster'] ?? '', $data['rating'] ?? 3.0, $data['review'] ?? '', $streaming]); $stmt->execute([$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $data['poster'] ?? '', $data['rating'] ?? 3.0, $data['review'] ?? '', $streaming]);
} else { } else {
if (empty($data['poster']) && !empty($data['title'])) { if (empty($data['poster']) && !empty($data['title'])) {
$format = $data['format'] ?: 'Blu-ray'; $cpData = fetchCinemaPassion($data['title'], $data['year'] ?? '', $data['ean_isbn13'] ?? '', $pdo);
$fanartData = fetchFanartTv($data['title'], $data['year'] ?? '', $format, $pdo); if (!empty($cpData['poster']) && $cpData['poster'] !== 'assets/img/default_physical_media.jpg') {
if (!empty($fanartData['poster'])) { $data['poster'] = $cpData['poster'];
$data['poster'] = $fanartData['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)"; $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 = $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'] ?? '']); $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'] ?? '']);
@@ -519,6 +395,7 @@ case 'get_config_keys':
$pdo->beginTransaction(); $pdo->beginTransaction();
$imported = 0; $imported = 0;
try {
if ($type === 'videotheque') { if ($type === 'videotheque') {
$stmtVideo = $pdo->prepare("INSERT INTO videotheque (id, title, year, format, poster, ean_isbn13, description, length, number_of_discs, aspect_ratio, actors, publisher, director) $stmtVideo = $pdo->prepare("INSERT INTO videotheque (id, title, year, format, poster, ean_isbn13, description, length, number_of_discs, aspect_ratio, actors, publisher, director)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -531,7 +408,8 @@ case 'get_config_keys':
number_of_discs = VALUES(number_of_discs), number_of_discs = VALUES(number_of_discs),
aspect_ratio = VALUES(aspect_ratio), aspect_ratio = VALUES(aspect_ratio),
actors = VALUES(actors), actors = VALUES(actors),
publisher = VALUES(publisher)"); publisher = VALUES(publisher),
director = VALUES(director)");
foreach ($items as $item) { foreach ($items as $item) {
$title = $item['title'] ?? ''; $title = $item['title'] ?? '';
@@ -549,17 +427,11 @@ case 'get_config_keys':
$id = makeStableId('videotheque', $title, $year); $id = makeStableId('videotheque', $title, $year);
// Utiliser cinemapassion.com pour récupérer l'image // ✅ UTILISER CINEMAPASSION.COM
$cinemaPassionData = fetchCinemaPassion($title, $year, $ean, $pdo); $cpData = fetchCinemaPassion($title, $year, $ean, $pdo);
$poster = $cinemaPassionData['poster']; $poster = $cpData['poster'];
// Déterminer le format $format = detectFormat($title, $desc);
$format = 'Blu-ray';
if (stripos($title, '4K') !== false || stripos($title, 'UHD') !== false) {
$format = '4K Ultra HD';
} elseif (stripos($desc, 'DVD') !== false) {
$format = 'DVD';
}
$stmtVideo->execute([ $stmtVideo->execute([
$id, $title, $year, $format, $poster, $ean, $desc, $id, $title, $year, $format, $poster, $ean, $desc,
@@ -568,7 +440,7 @@ case 'get_config_keys':
$imported++; $imported++;
} }
} else { } else {
// CORRECTION : Initialisation des variables manquantes // CORRECTION CRITIQUE : Initialisation des variables pour les critiques
$stmtCritiques = $pdo->prepare("INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) $stmtCritiques = $pdo->prepare("INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director),
@@ -605,10 +477,16 @@ case 'get_config_keys':
} }
$pdo->commit(); $pdo->commit();
echo json_encode(["success" => true, "imported" => $imported]); echo json_encode(["success" => true, "imported" => $imported]);
} catch (Exception $e) {
$pdo->rollBack();
error_log("import_batch error: " . $e->getMessage());
http_response_code(500);
echo json_encode(["success" => false, "error" => $e->getMessage()]);
}
break; break;
// ── ENDPOINT DE DEBUG DÉTAILLÉ ── // ── ENDPOINT DE DEBUG DÉTAILLÉ ──
case 'debug_cinemapassion_detailed': case 'debug_cinemapassion':
$title = $_GET['title'] ?? 'Saw'; $title = $_GET['title'] ?? 'Saw';
$year = $_GET['year'] ?? ''; $year = $_GET['year'] ?? '';
$ean = $_GET['ean'] ?? ''; $ean = $_GET['ean'] ?? '';
@@ -616,140 +494,75 @@ case 'debug_cinemapassion_detailed':
$debugInfo = [ $debugInfo = [
'title' => $title, 'title' => $title,
'year' => $year, 'year' => $year,
'ean' => $ean,
'cleanTitle' => cleanTitle($title), 'cleanTitle' => cleanTitle($title),
'steps' => [] 'steps' => []
]; ];
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'; // Test 1 : POST sur moteur2.php
$searchRes = httpPost('https://www.cinemapassion.com/moteur2.php', ['recherche' => cleanTitle($title)]);
// ÉTAPE 1 : Test de la recherche POST $debugInfo['steps']['search_post'] = [
$searchUrl = "https://www.cinemapassion.com/moteur2.php"; 'success' => !empty($searchRes),
$ch = curl_init($searchUrl); 'length' => $searchRes ? strlen($searchRes) : 0
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['recherche' => cleanTitle($title)]),
CURLOPT_REFERER => 'https://www.cinemapassion.com/',
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: fr-FR,fr;q=0.8',
'Origin: https://www.cinemapassion.com'
],
]);
$searchRes = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// ✅ CORRECTION : Vérifier que $searchRes est une string
$searchResStr = ($searchRes && is_string($searchRes)) ? $searchRes : '';
$debugInfo['steps']['search'] = [
'url' => $searchUrl,
'http_code' => $code,
'response_length' => strlen($searchResStr),
'success' => ($code === 200 && strlen($searchResStr) > 0)
]; ];
if ($code === 200 && strlen($searchResStr) > 0) { if ($searchRes) {
// ÉTAPE 2 : Extraction du lien film // Test 2 : Extraction du lien film
if (preg_match('/href=["\']([^"\']*film\/[^"\'\/]+-\d+\.php)["\']/i', $searchResStr, $matches)) { if (preg_match('/href=["\']?(?:\.\.\/)?film\/([^"\'\s]+)-(\d+)\.php["\']?/i', $searchRes, $matches)) {
$filmPath = $matches[1]; $debugInfo['steps']['film_found'] = [
$filmPath = str_replace('../', '', $filmPath); 'success' => true,
$filmUrl = 'https://www.cinemapassion.com/' . $filmPath; 'filmName' => $matches[1],
'filmId' => $matches[2]
$debugInfo['steps']['film_link'] = [
'found' => true,
'filmPath' => $filmPath,
'filmUrl' => $filmUrl
]; ];
// ÉTAPE 3 : Extraction du nom et ID $filmName = $matches[1];
if (preg_match('/film\/([^\/]+)-(\d+)\.php/i', $filmUrl, $filmMatches)) { $filmId = $matches[2];
$filmName = $filmMatches[1];
$filmId = $filmMatches[2];
$debugInfo['steps']['film_details'] = [ // Test 3 : Pages de jaquettes
'filmName' => $filmName,
'filmId' => $filmId
];
// ÉTAPE 4 : Test des pages de jaquettes
$pagesToTry = [ $pagesToTry = [
"https://www.cinemapassion.com/jaquette-dvd-{$filmName}-{$filmId}.php", "https://www.cinemapassion.com/jaquette-dvd-{$filmName}-{$filmId}.php",
"https://www.cinemapassion.com/jaquette-blu-ray-{$filmName}-{$filmId}.php", "https://www.cinemapassion.com/jaquette-blu-ray-{$filmName}-{$filmId}.php",
$filmUrl, "https://www.cinemapassion.com/film/{$filmName}-{$filmId}.php",
"https://www.cinemapassion.com/sticker-dvd-{$filmName}-{$filmId}.php",
]; ];
foreach ($pagesToTry as $index => $pageUrl) { foreach ($pagesToTry as $i => $pageUrl) {
$pageRes = httpGet($pageUrl, 10, $userAgent); $pageRes = httpGet($pageUrl, 10);
// ✅ CORRECTION : Vérifier que $pageRes est une string
$pageResStr = ($pageRes && is_string($pageRes)) ? $pageRes : '';
$pageDebug = [ $pageDebug = [
'url' => $pageUrl, 'url' => $pageUrl,
'success' => (strlen($pageResStr) > 0), 'success' => !empty($pageRes),
'response_length' => strlen($pageResStr) 'length' => $pageRes ? strlen($pageRes) : 0
]; ];
if (strlen($pageResStr) > 0) { if ($pageRes) {
// Test du pattern d'image if (preg_match('/src=["\']?(https?:\/\/(?:www\.)?cinemapassion\.com\/covers_temp\/covers\d*\/[^"\'\s>]+\.jpg)["\']?/i', $pageRes, $imgMatches)) {
if (preg_match('/src=["\']?(https?:\/\/[^"\'\s>]*cinemapassion\.com[^"\'\s>]*covers[^"\'\s>]*\.jpg)["\']?/i', $pageResStr, $imgMatches)) {
$posterUrl = str_replace('http://', 'https://', $imgMatches[1]);
$pageDebug['image_found'] = true; $pageDebug['image_found'] = true;
$pageDebug['image_url'] = $posterUrl; $pageDebug['image_url'] = str_replace('http://', 'https://', $imgMatches[1]);
} elseif (preg_match('/src=["\']?(https?:\/\/(?:www\.)?cinemapassion\.com\/lesaffiches\/[^"\'\s>]+\.jpg)["\']?/i', $pageRes, $imgMatches)) {
$debugInfo['steps']['pages_tested'][$index] = $pageDebug; $pageDebug['affiche_found'] = true;
$debugInfo['final_result'] = [ $pageDebug['image_url'] = str_replace('http://', 'https://', $imgMatches[1]);
'success' => true,
'poster' => $posterUrl,
'title' => cleanTitle($title),
'format' => 'Blu-ray'
];
echo json_encode($debugInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
} else { } else {
$pageDebug['image_found'] = false; $pageDebug['image_found'] = false;
// Extraire un extrait du HTML pour debug // Extraire un extrait pour debug
$pageDebug['html_snippet'] = substr($pageResStr, 0, 500); $pageDebug['html_snippet'] = substr($pageRes, 0, 1000);
} }
} }
$debugInfo['steps']['pages_tested'][$index] = $pageDebug; $debugInfo['steps']['pages'][$i] = $pageDebug;
}
}
} else {
$debugInfo['steps']['film_link'] = [
'found' => false,
'html_snippet' => substr($searchResStr, 0, 1000)
];
}
// Test du fallback if (!empty($pageDebug['image_found']) || !empty($pageDebug['affiche_found'])) {
if (preg_match('/src=["\']?(https?:\/\/[^"\'\s>]*cinemapassion\.com[^"\'\s>]*covers[^"\'\s>]*\.jpg)["\']?/i', $searchResStr, $imgMatches)) {
$posterUrl = str_replace('http://', 'https://', $imgMatches[1]);
$debugInfo['steps']['fallback'] = [
'success' => true,
'image_url' => $posterUrl
];
$debugInfo['final_result'] = [ $debugInfo['final_result'] = [
'success' => true, 'success' => true,
'poster' => $posterUrl, 'poster' => $pageDebug['image_url'],
'title' => cleanTitle($title), 'title' => cleanTitle($title),
'format' => 'Blu-ray' 'format' => 'Blu-ray'
]; ];
echo json_encode($debugInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
}
} else { } else {
$debugInfo['steps']['fallback'] = [ $debugInfo['steps']['film_found'] = [
'success' => false 'success' => false,
'html_snippet' => substr($searchRes, 0, 2000)
]; ];
} }
} }
@@ -757,9 +570,7 @@ case 'debug_cinemapassion_detailed':
if (!isset($debugInfo['final_result'])) { if (!isset($debugInfo['final_result'])) {
$debugInfo['final_result'] = [ $debugInfo['final_result'] = [
'success' => false, 'success' => false,
'poster' => 'assets/img/default_physical_media.jpg', 'poster' => 'assets/img/default_physical_media.jpg'
'title' => cleanTitle($title),
'format' => 'Blu-ray'
]; ];
} }