Actualiser api.php
This commit is contained in:
@@ -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 ──
|
||||||
|
|||||||
Reference in New Issue
Block a user