Actualiser api.php
This commit is contained in:
@@ -60,10 +60,22 @@ function getTmdbApiKey($pdo) {
|
|||||||
return $row ? decryptData($row['key_value']) : null;
|
return $row ? decryptData($row['key_value']) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function httpGet($url, $timeout = 5, $ua = null) {
|
function getUpcmdbApiKey($pdo) {
|
||||||
|
$stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name = 'upcmdb_api_key'");
|
||||||
|
$stmt->execute();
|
||||||
|
$row = $stmt->fetch();
|
||||||
|
return $row ? decryptData($row['key_value']) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpGet($url, $timeout = 5, $ua = null, $extraHeaders = []) {
|
||||||
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';
|
||||||
|
$headers = array_merge(
|
||||||
|
['Accept: application/json, text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language: fr-FR,fr;q=0.8'],
|
||||||
|
$extraHeaders
|
||||||
|
);
|
||||||
if (!function_exists('curl_init')) {
|
if (!function_exists('curl_init')) {
|
||||||
$ctx = stream_context_create(['http' => ['timeout' => $timeout, 'user_agent' => $ua]]);
|
$headerLines = implode("\r\n", $headers);
|
||||||
|
$ctx = stream_context_create(['http' => ['timeout' => $timeout, 'user_agent' => $ua, 'header' => $headerLines]]);
|
||||||
$res = @file_get_contents($url, false, $ctx);
|
$res = @file_get_contents($url, false, $ctx);
|
||||||
return $res ?: null;
|
return $res ?: null;
|
||||||
}
|
}
|
||||||
@@ -76,7 +88,7 @@ function httpGet($url, $timeout = 5, $ua = null) {
|
|||||||
CURLOPT_USERAGENT => $ua,
|
CURLOPT_USERAGENT => $ua,
|
||||||
CURLOPT_FOLLOWLOCATION => true,
|
CURLOPT_FOLLOWLOCATION => true,
|
||||||
CURLOPT_REFERER => 'https://www.cinemapassion.com/',
|
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'],
|
CURLOPT_HTTPHEADER => $headers,
|
||||||
]);
|
]);
|
||||||
$res = curl_exec($ch);
|
$res = curl_exec($ch);
|
||||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
@@ -101,6 +113,125 @@ function detectFormat($title, $desc = '') {
|
|||||||
return 'Blu-ray';
|
return 'Blu-ray';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseDiscCountFromTitle($title) {
|
||||||
|
if (preg_match('/(\d+)\s*(?:dvd|blu-?ray|bluray|bd|disc|disque)/i', $title, $m)) {
|
||||||
|
return max(1, (int)$m[1]);
|
||||||
|
}
|
||||||
|
if (preg_match('/(?:coffret|pack|collection|trilogie|anthologie).*?(\d+)/i', $title, $m)) {
|
||||||
|
return max(1, (int)$m[1]);
|
||||||
|
}
|
||||||
|
if (preg_match('/\btrilogie\b/i', $title)) return 3;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanUpcTitle($title) {
|
||||||
|
$clean = trim($title);
|
||||||
|
$clean = preg_replace('/^[\s"]*(DVD|Blu-ray|Blu Ray|4K|UHD)[\s"]*/i', '', $clean);
|
||||||
|
$clean = preg_replace('/(blu-ray|bluray|dvd|4k|ultra hd|combo|vhs|blister pack|new blister).*$/i', '', $clean);
|
||||||
|
$clean = preg_replace('/[\s"]+New[\s"]*$/i', '', $clean);
|
||||||
|
return cleanTitle($clean);
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptyPhysicalResult() {
|
||||||
|
return [
|
||||||
|
'title' => '', 'publisher' => '', 'format' => '', 'length' => '',
|
||||||
|
'number_of_discs' => 1, 'aspect_ratio' => '', 'year' => ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function throttleUpcLookup() {
|
||||||
|
static $lastLookupAt = 0;
|
||||||
|
$elapsed = microtime(true) - $lastLookupAt;
|
||||||
|
if ($lastLookupAt > 0 && $elapsed < 2) {
|
||||||
|
usleep((int)((2 - $elapsed) * 1000000));
|
||||||
|
}
|
||||||
|
$lastLookupAt = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── API GRATUITE UPCitemdb : métadonnées physiques via EAN/UPC ──
|
||||||
|
function fetchPhysicalFromUpcitemdb($ean) {
|
||||||
|
$empty = emptyPhysicalResult();
|
||||||
|
$ean = preg_replace('/[^0-9]/', '', (string)$ean);
|
||||||
|
if (strlen($ean) < 8) return $empty;
|
||||||
|
|
||||||
|
throttleUpcLookup();
|
||||||
|
|
||||||
|
$url = 'https://api.upcitemdb.com/prod/trial/lookup?upc=' . urlencode($ean);
|
||||||
|
$res = httpGet($url, 10, 'MonPetitCinema/1.0');
|
||||||
|
if (!$res) return $empty;
|
||||||
|
|
||||||
|
$data = json_decode($res, true);
|
||||||
|
if (empty($data['items'][0])) return $empty;
|
||||||
|
|
||||||
|
$item = $data['items'][0];
|
||||||
|
$rawTitle = $item['title'] ?? '';
|
||||||
|
$title = cleanUpcTitle($rawTitle) ?: trim($rawTitle);
|
||||||
|
$publisher = trim($item['brand'] ?? '');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'title' => $title,
|
||||||
|
'publisher' => $publisher,
|
||||||
|
'format' => detectFormat($rawTitle),
|
||||||
|
'length' => '',
|
||||||
|
'number_of_discs' => parseDiscCountFromTitle($rawTitle),
|
||||||
|
'aspect_ratio' => '',
|
||||||
|
'year' => ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── API UPCMDB (clé gratuite) : fallback spécialisé DVD/Blu-ray/4K ──
|
||||||
|
function fetchPhysicalFromUpcmdb($ean, $pdo) {
|
||||||
|
$empty = emptyPhysicalResult();
|
||||||
|
$apiKey = getUpcmdbApiKey($pdo);
|
||||||
|
if (!$apiKey) return $empty;
|
||||||
|
|
||||||
|
$ean = preg_replace('/[^0-9]/', '', (string)$ean);
|
||||||
|
if (strlen($ean) < 8) return $empty;
|
||||||
|
|
||||||
|
$url = 'https://upcmdb.com/api/v1/lookup/' . urlencode($ean);
|
||||||
|
$res = httpGet($url, 10, 'MonPetitCinema/1.0', [
|
||||||
|
'Accept: application/json',
|
||||||
|
'X-API-Key: ' . $apiKey
|
||||||
|
]);
|
||||||
|
if (!$res || $res[0] === '<') return $empty;
|
||||||
|
|
||||||
|
$data = json_decode($res, true);
|
||||||
|
if (($data['status'] ?? '') !== 'success' || empty($data['data'])) return $empty;
|
||||||
|
|
||||||
|
$item = $data['data'];
|
||||||
|
$rawTitle = trim($item['title'] ?? '');
|
||||||
|
if ($rawTitle === '') return $empty;
|
||||||
|
|
||||||
|
$title = cleanUpcTitle($rawTitle) ?: $rawTitle;
|
||||||
|
$format = trim($item['format'] ?? '');
|
||||||
|
$runtime = trim($item['runtime'] ?? '');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'title' => $title,
|
||||||
|
'publisher' => trim($item['studio'] ?? $item['publisher'] ?? ''),
|
||||||
|
'format' => $format !== '' ? $format : detectFormat($rawTitle),
|
||||||
|
'length' => $runtime,
|
||||||
|
'number_of_discs' => parseDiscCountFromTitle($rawTitle),
|
||||||
|
'aspect_ratio' => trim($item['aspect_ratio'] ?? ''),
|
||||||
|
'year' => trim($item['year'] ?? '')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchPhysicalByEan($ean, $pdo = null) {
|
||||||
|
$result = fetchPhysicalFromUpcitemdb($ean);
|
||||||
|
if (!empty($result['title'])) return $result;
|
||||||
|
|
||||||
|
if ($pdo) {
|
||||||
|
$fallback = fetchPhysicalFromUpcmdb($ean, $pdo);
|
||||||
|
if (!empty($fallback['title'])) {
|
||||||
|
error_log("UPCMDB: ✅ Fallback trouvé pour EAN {$ean} → {$fallback['title']}");
|
||||||
|
return $fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
// ── FONCTION POUR RÉCUPÉRER LES AFFICHES DEPUIS TMDB ──
|
// ── FONCTION POUR RÉCUPÉRER LES AFFICHES DEPUIS TMDB ──
|
||||||
function fetchPosterTMDB($title, $year = '', $pdo = null) {
|
function fetchPosterTMDB($title, $year = '', $pdo = null) {
|
||||||
$defaultPoster = 'assets/img/default_physical_media.jpg';
|
$defaultPoster = 'assets/img/default_physical_media.jpg';
|
||||||
@@ -291,7 +422,7 @@ switch ($action) {
|
|||||||
|
|
||||||
case 'get_config_keys':
|
case 'get_config_keys':
|
||||||
checkAuth($pdo);
|
checkAuth($pdo);
|
||||||
$stmt = $pdo->prepare("SELECT key_name, key_value FROM config WHERE key_name IN ('tmdb_api_key', 'fanart_api_key')");
|
$stmt = $pdo->prepare("SELECT key_name, key_value FROM config WHERE key_name IN ('tmdb_api_key', 'fanart_api_key', 'upcmdb_api_key')");
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$rows = $stmt->fetchAll();
|
$rows = $stmt->fetchAll();
|
||||||
$config = [];
|
$config = [];
|
||||||
@@ -300,6 +431,7 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
if (!isset($config['tmdb_api_key'])) $config['tmdb_api_key'] = '';
|
if (!isset($config['tmdb_api_key'])) $config['tmdb_api_key'] = '';
|
||||||
if (!isset($config['fanart_api_key'])) $config['fanart_api_key'] = '';
|
if (!isset($config['fanart_api_key'])) $config['fanart_api_key'] = '';
|
||||||
|
if (!isset($config['upcmdb_api_key'])) $config['upcmdb_api_key'] = '';
|
||||||
echo json_encode($config);
|
echo json_encode($config);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -307,7 +439,7 @@ switch ($action) {
|
|||||||
checkAuth($pdo);
|
checkAuth($pdo);
|
||||||
$keyName = $data['key_name'] ?? '';
|
$keyName = $data['key_name'] ?? '';
|
||||||
$keyValue = $data['key_value'] ?? '';
|
$keyValue = $data['key_value'] ?? '';
|
||||||
if (in_array($keyName, ['tmdb_api_key', 'fanart_api_key']) && !empty($keyValue)) {
|
if (in_array($keyName, ['tmdb_api_key', 'fanart_api_key', 'upcmdb_api_key']) && !empty($keyValue)) {
|
||||||
$stmt = $pdo->prepare("REPLACE INTO config (key_name, key_value) VALUES (?, ?)");
|
$stmt = $pdo->prepare("REPLACE INTO config (key_name, key_value) VALUES (?, ?)");
|
||||||
$stmt->execute([$keyName, encryptData($keyValue)]);
|
$stmt->execute([$keyName, encryptData($keyValue)]);
|
||||||
echo json_encode(["success" => true]);
|
echo json_encode(["success" => true]);
|
||||||
@@ -319,10 +451,10 @@ switch ($action) {
|
|||||||
|
|
||||||
case 'get_films':
|
case 'get_films':
|
||||||
$sql = "
|
$sql = "
|
||||||
SELECT id, title, year, director, poster, rating, review, NULL AS description, streaming, 'critique' AS type
|
SELECT id, title, year, director, poster, rating, review, NULL AS description, streaming, 'critique' AS type, NULL AS format
|
||||||
FROM critiques
|
FROM critiques
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT id, title, year, director, poster, NULL AS rating, NULL AS review, description, NULL AS streaming, 'videotheque' AS type
|
SELECT id, title, year, director, poster, NULL AS rating, NULL AS review, description, NULL AS streaming, 'videotheque' AS type, format
|
||||||
FROM videotheque
|
FROM videotheque
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
";
|
";
|
||||||
@@ -343,7 +475,7 @@ switch ($action) {
|
|||||||
$id = !empty($data['id']) ? $data['id'] : makeStableId($type, $data['title'] ?? '', $data['year'] ?? '0000');
|
$id = !empty($data['id']) ? $data['id'] : makeStableId($type, $data['title'] ?? '', $data['year'] ?? '0000');
|
||||||
|
|
||||||
if ($type === 'critique' && (empty($data['director']) || empty($data['poster']))) {
|
if ($type === 'critique' && (empty($data['director']) || empty($data['poster']))) {
|
||||||
$tmdbData = fetchTMDBFull($data['title'] ?? '', $data['year'] ?? '', getTmdbApiKey($pdo), $pdo);
|
$tmdbData = fetchTmdbPosterAndSynopsis($data['title'] ?? '', $data['year'] ?? '', $pdo);
|
||||||
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'];
|
||||||
@@ -401,6 +533,7 @@ $type = $data['type'] ?? 'critique';
|
|||||||
$items = $data['items'] ?? [];
|
$items = $data['items'] ?? [];
|
||||||
$pdo->beginTransaction();
|
$pdo->beginTransaction();
|
||||||
$imported = 0;
|
$imported = 0;
|
||||||
|
$skipped = 0;
|
||||||
try {
|
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)
|
||||||
@@ -419,32 +552,34 @@ try {
|
|||||||
year = VALUES(year)");
|
year = VALUES(year)");
|
||||||
|
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$title = $item['title'] ?? '';
|
// ── SOURCE 1 : CSV → EAN uniquement ──
|
||||||
if (empty($title)) continue;
|
$ean = preg_replace('/[^0-9]/', '', (string)($item['ean'] ?? ''));
|
||||||
$year = $item['year'] ?? '';
|
if (strlen($ean) < 8) { $skipped++; continue; }
|
||||||
$id = makeStableId('videotheque', $title, $year);
|
|
||||||
|
|
||||||
// ── SOURCE 1 : CSV (Informations physiques uniquement) ──
|
// ── SOURCE 2 : UPCitemdb (gratuit) → métadonnées physiques ──
|
||||||
$ean = $item['ean'] ?? '';
|
$physical = fetchPhysicalByEan($ean, $pdo);
|
||||||
$format = $item['format'] ?? '';
|
$title = $physical['title'] ?? '';
|
||||||
$publisher = $item['publisher'] ?? '';
|
if (empty($title)) { $skipped++; continue; }
|
||||||
$discs = $item['number_of_discs'] ?? 1;
|
|
||||||
$aspect = $item['aspect_ratio'] ?? '';
|
|
||||||
$length = $item['length'] ?? '';
|
|
||||||
|
|
||||||
// On initialise avec le CSV, mais l'API TMDB va écraser ces valeurs si elle trouve mieux
|
$year = $physical['year'] ?? '';
|
||||||
$description = $item['description'] ?? '';
|
$format = $physical['format'] ?? '';
|
||||||
$director = $item['director'] ?? '';
|
$publisher = $physical['publisher'] ?? '';
|
||||||
$actors = $item['actors'] ?? '';
|
$discs = $physical['number_of_discs'] ?? 1;
|
||||||
|
$aspect = $physical['aspect_ratio'] ?? '';
|
||||||
|
$length = $physical['length'] ?? '';
|
||||||
|
$id = makeStableId('videotheque', $ean, $title);
|
||||||
|
|
||||||
|
$description = '';
|
||||||
|
$director = '';
|
||||||
|
$actors = '';
|
||||||
$poster = 'assets/img/default_physical_media.jpg';
|
$poster = 'assets/img/default_physical_media.jpg';
|
||||||
|
|
||||||
// ── SOURCE 2 : API TMDB (Priorité absolue pour les métadonnées) ──
|
// ── SOURCE 3 : TMDB → affiche, synopsis, réalisateur, acteurs ──
|
||||||
$tmdbData = fetchTmdbPosterAndSynopsis($title, $year, $pdo);
|
$tmdbData = fetchTmdbPosterAndSynopsis($title, $year, $pdo);
|
||||||
if ($tmdbData) {
|
if ($tmdbData) {
|
||||||
if ($tmdbData['poster'] !== 'assets/img/default_physical_media.jpg') {
|
if ($tmdbData['poster'] !== 'assets/img/default_physical_media.jpg') {
|
||||||
$poster = $tmdbData['poster'];
|
$poster = $tmdbData['poster'];
|
||||||
}
|
}
|
||||||
// Écrasement des données CSV par l'API TMDB si disponibles
|
|
||||||
if (!empty($tmdbData['description'])) $description = $tmdbData['description'];
|
if (!empty($tmdbData['description'])) $description = $tmdbData['description'];
|
||||||
if (!empty($tmdbData['director'])) $director = $tmdbData['director'];
|
if (!empty($tmdbData['director'])) $director = $tmdbData['director'];
|
||||||
if (!empty($tmdbData['actors'])) $actors = $tmdbData['actors'];
|
if (!empty($tmdbData['actors'])) $actors = $tmdbData['actors'];
|
||||||
@@ -491,7 +626,7 @@ try {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
echo json_encode(["success" => true, "imported" => $imported]);
|
echo json_encode(["success" => true, "imported" => $imported, "skipped" => $skipped]);
|
||||||
|
|
||||||
} catch (Throwable $e) { // ── CORRECTION ICI : Throwable capture les Crash Fatals PHP ──
|
} catch (Throwable $e) { // ── CORRECTION ICI : Throwable capture les Crash Fatals PHP ──
|
||||||
$pdo->rollBack();
|
$pdo->rollBack();
|
||||||
|
|||||||
Reference in New Issue
Block a user