Actualiser api.php

This commit is contained in:
2026-06-24 11:27:44 +02:00
parent 325a6df04e
commit db8cab0add
+80 -68
View File
@@ -7,7 +7,6 @@ header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; } if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }
define('ENCRYPTION_KEY', 'MaCleSecreteSuperRobuste123!'); define('ENCRYPTION_KEY', 'MaCleSecreteSuperRobuste123!');
define('CACHE_TTL', 604800); // 7 jours
try { try {
$pdo = new PDO("mysql:host=localhost;dbname=mon_cinema;charset=utf8mb4", "root", "", [ $pdo = new PDO("mysql:host=localhost;dbname=mon_cinema;charset=utf8mb4", "root", "", [
@@ -24,7 +23,6 @@ try {
$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) {}
$pdo->exec("CREATE TABLE IF NOT EXISTS cache_api (cache_key VARCHAR(120) PRIMARY KEY, data TEXT NOT NULL, source VARCHAR(20) NOT NULL, created_at INT NOT NULL)");
} 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 ──
@@ -76,22 +74,6 @@ function httpGet($url, $timeout = 5) {
return $res ?: null; return $res ?: null;
} }
function getCache($pdo, $key) {
try {
$stmt = $pdo->prepare("SELECT data FROM cache_api WHERE cache_key = ? AND created_at > ?");
$stmt->execute([$key, time() - CACHE_TTL]);
$row = $stmt->fetch();
return $row ? json_decode($row['data'], true) : null;
} catch (\Exception $e) { return null; }
}
function setCache($pdo, $key, $data, $source) {
try {
$stmt = $pdo->prepare("REPLACE INTO cache_api (cache_key, data, source, created_at) VALUES (?, ?, ?, ?)");
$stmt->execute([$key, json_encode($data), $source, time()]);
} catch (\Exception $e) { /* ignore */ }
}
function cleanTitle($title) { function cleanTitle($title) {
$clean = preg_replace('/\s*[\[\(].*?[\]\)]\s*/', '', $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); $clean = preg_replace('/\s*-\s*(Édition|Edition|Collector|Simple|Spéciale|Digibook|Ultimate|Intégrale|Combo|SteelBook|Boîtier).*$/i', '', $clean);
@@ -117,66 +99,99 @@ function extractYear($dateStr) {
function fetchDVDFr($ean, $pdo) { function fetchDVDFr($ean, $pdo) {
if (empty($ean) || strlen($ean) < 8) return null; if (empty($ean) || strlen($ean) < 8) return null;
$cacheKey = 'dvdfr_full_' . md5($ean);
$cached = getCache($pdo, $cacheKey);
if ($cached) return $cached;
$url = "https://www.dvdfr.com/api/search.php?gencode=" . urlencode($ean); $ua = 'MonCinema/1.0 (collection privée; contact@moncineapp.fr)';
$res = httpGet($url, 10); // Augmenté à 10s pour éviter les timeouts
if (!$res) {
file_put_contents('dvdfr_error.log', "Échec requête pour EAN: $ean");
return null;
}
try { // Étape 1 : recherche par gencode
$xml = @simplexml_load_string($res); $searchUrl = "https://www.dvdfr.com/api/search.php?gencode=" . urlencode($ean);
if ($xml && isset($xml->dvd[0])) { $ch = curl_init($searchUrl);
$d = $xml->dvd[0]; curl_setopt_array($ch, [
// On extrait tout ce que DVDfr nous donne CURLOPT_RETURNTRANSFER => true,
$data = [ CURLOPT_TIMEOUT => 5,
'poster' => (string)$d->cover, CURLOPT_CONNECTTIMEOUT => 3,
'format' => (string)$d->media, CURLOPT_SSL_VERIFYPEER => false,
'publisher' => (string)$d->editor, CURLOPT_USERAGENT => $ua,
'length' => (string)$d->duration, CURLOPT_FOLLOWLOCATION => true,
'aspect' => (string)$d->ratio CURLOPT_HTTPHEADER => ['Accept: application/xml, text/xml, */*'],
]; ]);
$res = curl_exec($ch);
curl_close($ch);
if (!$res) return null;
setCache($pdo, $cacheKey, $data, 'dvdfr'); libxml_use_internal_errors(true);
return $data; $xml = simplexml_load_string($res);
} libxml_clear_errors();
} catch (\Exception $e) { return null; } if (!$xml || !isset($xml->dvd[0]->id)) return null;
return null;
$dvdId = (string)$xml->dvd[0]->id;
if (empty($dvdId)) return null;
// Étape 2 : fiche complète
$ficheUrl = "https://www.dvdfr.com/api/dvd.php?id=" . urlencode($dvdId);
$ch2 = curl_init($ficheUrl);
curl_setopt_array($ch2, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => $ua,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTPHEADER => ['Accept: application/xml, text/xml, */*'],
]);
$res2 = curl_exec($ch2);
curl_close($ch2);
if (!$res2) return null;
libxml_use_internal_errors(true);
$fiche = simplexml_load_string($res2);
libxml_clear_errors();
if (!$fiche || !isset($fiche->dvd[0])) return null;
$dvd = $fiche->dvd[0];
$poster = '';
if (isset($dvd->cover)) $poster = (string)$dvd->cover;
if (empty($poster) && isset($dvd->covers->cover[0])) $poster = (string)$dvd->covers->cover[0];
$result = [
'poster' => $poster,
'publisher' => isset($dvd->editeur) ? (string)$dvd->editeur : '',
'format' => isset($dvd->type) ? (string)$dvd->type : '',
'length' => isset($dvd->duree) ? (string)$dvd->duree : '',
'aspect' => isset($dvd->formatimage) ? (string)$dvd->formatimage : '',
'discs' => isset($dvd->nbdisques) ? (string)$dvd->nbdisques : '',
];
return !empty($result['poster']) || !empty($result['publisher']) ? $result : null;
} }
// ── 2. API TMDB (Full Extract avec Synopsis et Acteurs) ──
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);
$cacheKey = 'tmdb_full_' . md5(strtolower($cleanTitle) . '|' . $year);
$cached = getCache($pdo, $cacheKey);
if ($cached) return $cached;
// 1. Tenter avec l'année $cleanTitle = cleanTitle($title);
// 1. Recherche avec l'année
$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 = json_decode($searchRes, true); $searchData = $searchRes ? json_decode($searchRes, true) : [];
// 2. Fallback : Si rien trouvé, on réessaie SANS l'année (au cas où l'année dans le CSV soit fausse) // 2. Fallback sans l'année
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 = 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'];
// 3. Détails complets
$detailsUrl = "https://api.themoviedb.org/3/movie/{$movieId}?api_key={$apiKey}&append_to_response=credits,watch/providers&language=fr-FR"; $detailsUrl = "https://api.themoviedb.org/3/movie/{$movieId}?api_key={$apiKey}&append_to_response=credits,watch/providers&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);
// 🔥 Extraction de TOUS les Réalisateurs (pour les co-réalisations) // Extraction Réalisateurs
$director = ''; $director = '';
if (!empty($details['credits']['crew'])) { if (!empty($details['credits']['crew'])) {
$directorsList = []; $directorsList = [];
@@ -188,7 +203,7 @@ function fetchTMDBFull($title, $year, $apiKey, $pdo) {
$director = implode(', ', $directorsList); $director = implode(', ', $directorsList);
} }
// 🔥 Extraction des 4 premiers Acteurs // Extraction Acteurs (Top 4)
$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);
@@ -197,10 +212,10 @@ function fetchTMDBFull($title, $year, $apiKey, $pdo) {
} }
} }
// 🔥 Extraction du Synopsis (Overview) // Synopsis
$overview = $details['overview'] ?? ''; $overview = $details['overview'] ?? '';
// Extraction Streaming // Streaming
$streaming = ''; $streaming = '';
$frProviders = $details['watch/providers']['results']['FR'] ?? []; $frProviders = $details['watch/providers']['results']['FR'] ?? [];
$platforms = []; $platforms = [];
@@ -211,19 +226,16 @@ function fetchTMDBFull($title, $year, $apiKey, $pdo) {
} }
if (!empty($platforms)) $streaming = implode(', ', array_unique($platforms)); if (!empty($platforms)) $streaming = implode(', ', array_unique($platforms));
$result = [ return [
'title' => $details['title'] ?? '', 'title' => $details['title'] ?? '',
'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' => $overview,
'cast' => $cast 'cast' => $cast
]; ];
setCache($pdo, $cacheKey, $result, 'tmdb');
return $result;
} }
// ── ROUTEUR PRINCIPAL ── // ── ROUTEUR PRINCIPAL ──