Actualiser api.php

This commit is contained in:
2026-06-25 16:14:29 +02:00
parent 1f0fce2c4d
commit 3dd61b4fb0
+93 -123
View File
@@ -62,6 +62,13 @@ function getTmdbApiKey($pdo) {
return $row ? decryptData($row['key_value']) : null;
}
function getFanartApiKey($pdo) {
$stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name = 'fanart_api_key'");
$stmt->execute();
$row = $stmt->fetch();
return $row ? decryptData($row['key_value']) : null;
}
function httpGet($url, $timeout = 3, $ua = null) {
if (!$ua) $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
@@ -113,142 +120,95 @@ function extractYear($dateStr) {
return '';
}
// ── DVDCover.com via API REST WordPress ──
function fetchDVDCover($title, $year = '', $format = 'bluray') {
function fetchFanartTv($title, $year = '', $format = 'bluray', $pdo = null) {
if (empty($title)) return null;
$cleanTitle = cleanTitle($title);
if (empty($cleanTitle)) return null;
// API REST WordPress de DVDcover
$searchUrl = "https://www.dvdcover.com/wp-json/wp/v2/posts?search=" . urlencode($cleanTitle) . "&_embed&per_page=10";
// Récupérer la clé API
$apiKey = getFanartApiKey($pdo);
if (empty($apiKey)) {
// Fallback sur la clé en dur si non configurée
$apiKey = '70f9747dafe9b27f9b14ef80ee0cacc9';
}
$json = httpGet($searchUrl, 10);
if (!$json) {
error_log("DVDCover API: Échec requête pour '$title'");
// Étape 1 : Chercher le film sur TMDB pour obtenir son ID
$tmdbKey = getTmdbApiKey($pdo);
if (!$tmdbKey) {
error_log("Fanart.tv: Clé TMDB requise pour obtenir l'ID du film");
return null;
}
$posts = json_decode($json, true);
if (!is_array($posts) || empty($posts)) {
error_log("DVDCover API: Aucun résultat pour '$title'");
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query=" . urlencode($cleanTitle);
if (!empty($year)) {
$searchUrl .= "&year={$year}";
}
$searchRes = httpGet($searchUrl, 5);
$searchData = $searchRes ? json_decode($searchRes, true) : [];
if (empty($searchData['results'])) {
error_log("Fanart.tv: Film non trouvé sur TMDB pour '$title'");
return null;
}
$cleanTitleLower = strtolower($cleanTitle);
$bestPost = null;
$bestScore = 0;
$tmdbId = $searchData['results'][0]['id'];
foreach ($posts as $post) {
$postTitle = $post['title']['rendered'] ?? '';
$postTitleLower = strtolower($postTitle);
// Étape 2 : Récupérer les artworks depuis fanart.tv
$fanartUrl = "https://webservice.fanart.tv/v3/movies/{$tmdbId}?api_key={$apiKey}";
$fanartRes = httpGet($fanartUrl, 5);
$fanartData = $fanartRes ? json_decode($fanartRes, true) : [];
$score = 0;
if (strpos($postTitleLower, $cleanTitleLower) !== false) {
$score += 50;
}
if (!empty($year) && strpos($postTitle, $year) !== false) {
$score += 30;
}
$formatLower = strtolower($format);
if (stripos($postTitle, $format) !== false ||
stripos($postTitle, str_replace('-', ' ', $format)) !== false) {
$score += 20;
}
if (stripos($postTitle, 'cover') !== false) {
$score += 10;
}
if ($score > $bestScore) {
$bestScore = $score;
$bestPost = $post;
}
if ($score >= 100) break;
if (isset($fanartData['error'])) {
error_log("Fanart.tv: Erreur API - " . $fanartData['error']);
return null;
}
if (!$bestPost && !empty($posts)) {
$bestPost = $posts[0];
}
if (!$bestPost) return null;
// Extraire l'image du post
$poster = '';
// Méthode 1 : Image mise en avant (_embedded.wp:featuredmedia)
if (isset($bestPost['_embedded']['wp:featuredmedia'][0])) {
$featured = $bestPost['_embedded']['wp:featuredmedia'][0];
if (!empty($featured['media_details']['sizes'])) {
$sizes = $featured['media_details']['sizes'];
$preferredSizes = ['full', 'large', 'medium', 'thumbnail'];
foreach ($preferredSizes as $size) {
if (isset($sizes[$size]['source_url'])) {
$poster = $sizes[$size]['source_url'];
break;
}
// Priorité aux movieposter (jaquettes complètes)
if (!empty($fanartData['movieposter'])) {
// Filtrer par langue (fr d'abord, puis en, puis tout)
$posters = $fanartData['movieposter'];
$preferredLangs = ['fr', 'en', ''];
foreach ($preferredLangs as $lang) {
$filtered = array_filter($posters, function($p) use ($lang) {
return ($lang === '' || ($p['lang'] ?? '') === $lang);
});
if (!empty($filtered)) {
// Trier par likes (le plus populaire en premier)
usort($filtered, function($a, $b) {
return ($b['likes'] ?? 0) - ($a['likes'] ?? 0);
});
$poster = $filtered[0]['url'];
break;
}
}
if (empty($poster) && !empty($featured['source_url'])) {
$poster = $featured['source_url'];
}
}
// Méthode 2 : Images dans le contenu du post
if (empty($poster) && !empty($bestPost['content']['rendered'])) {
$content = $bestPost['content']['rendered'];
if (preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) {
foreach ($matches[1] as $img) {
if (strpos($img, 'logo') === false &&
strpos($img, 'icon') === false &&
strpos($img, 'banner') === false &&
strpos($img, 'bg') === false &&
strpos($img, 'button') === false &&
strpos($img, 'social') === false &&
(strpos($img, '.jpg') !== false || strpos($img, '.jpeg') !== false || strpos($img, '.png') !== false || strpos($img, '.webp') !== false)) {
$poster = $img;
break;
}
}
}
// Fallback sur hdmovielogo si pas de movieposter
if (empty($poster) && !empty($fanartData['hdmovielogo'])) {
$logos = $fanartData['hdmovielogo'];
$poster = $logos[0]['url'];
}
// Fallback sur moviebackground
if (empty($poster) && !empty($fanartData['moviebackground'])) {
$backgrounds = $fanartData['moviebackground'];
$poster = $backgrounds[0]['url'];
}
if (empty($poster)) {
error_log("DVDCover API: Pas d'image trouvée pour le post ID " . ($bestPost['id'] ?? '?'));
error_log("Fanart.tv: Aucune jaquette trouvée pour TMDB ID {$tmdbId}");
return null;
}
// S'assurer que l'URL est absolue
if (strpos($poster, 'http') !== 0) {
$poster = 'https://www.dvdcover.com' . (strpos($poster, '/') === 0 ? '' : '/') . ltrim($poster, '/');
}
// Supprimer les suffixes de taille WordPress
$poster = preg_replace('/-\d+x\d+(\.\w+)$/', '$1', $poster);
// VÉRIFICATION : Tester si l'image est accessible
// Essayer différentes variantes d'URL
$urlVariants = [
$poster,
str_replace('dvdcover.com', 'www.dvdcover.com', $poster),
str_replace('https://www.dvdcover.com', 'https://dvdcover.com', $poster),
];
foreach ($urlVariants as $testUrl) {
if (urlExists($testUrl, 3)) {
error_log("DVDCover API: Image valide trouvée - $testUrl");
return [
'poster' => $testUrl,
'title' => $bestPost['title']['rendered'] ?? $cleanTitle,
'format' => $format,
];
}
}
// Si aucune URL ne fonctionne, retourner quand même la première (peut-être un problème temporaire)
error_log("DVDCover API: Aucune URL d'image valide trouvée, retour de la première URL");
return [
'poster' => $poster,
'title' => $bestPost['title']['rendered'] ?? $cleanTitle,
'title' => $cleanTitle,
'format' => $format,
];
}
@@ -384,23 +344,35 @@ switch ($action) {
case 'get_config_keys':
checkAuth($pdo);
$stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name = 'tmdb_api_key'");
$stmt->execute(); $row = $stmt->fetch();
echo json_encode(['tmdb_api_key' => $row ? '••••••••' : '']);
$stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name IN ('tmdb_api_key', 'fanart_api_key')");
$stmt->execute();
$rows = $stmt->fetchAll();
$config = [];
foreach ($rows as $row) {
if ($row['key_name'] === 'tmdb_api_key') {
$config['tmdb_api_key'] = $row['key_value'] ? '••••••••' : '';
} elseif ($row['key_name'] === 'fanart_api_key') {
$config['fanart_api_key'] = $row['key_value'] ? '••••••••' : '';
}
}
// Valeurs par défaut si non configurées
if (!isset($config['tmdb_api_key'])) $config['tmdb_api_key'] = '';
if (!isset($config['fanart_api_key'])) $config['fanart_api_key'] = '';
echo json_encode($config);
break;
case 'save_config':
checkAuth($pdo);
$keyName = $data['key_name'] ?? '';
$keyValue = $data['key_value'] ?? '';
if ($keyName === 'tmdb_api_key' && !empty($keyValue)) {
if (in_array($keyName, ['tmdb_api_key', 'fanart_api_key']) && !empty($keyValue)) {
$stmt = $pdo->prepare("REPLACE INTO config (key_name, key_value) VALUES (?, ?)");
$stmt->execute([$keyName, encryptData($keyValue)]);
echo json_encode(["success" => true]);
} else {
http_response_code(400); echo json_encode(["error" => "Données invalides."]);
}
break;
break;
case 'get_films':
$sql = "
@@ -413,7 +385,7 @@ switch ($action) {
";
$result = $pdo->query($sql)->fetchAll();
foreach ($result as &$row) {
foreach ($result as $row) {
if ($row['rating'] !== null) {
$ratingVal = (float)$row['rating'];
$row['rating'] = ($ratingVal == floor($ratingVal)) ? (int)$ratingVal : $ratingVal;
@@ -456,10 +428,9 @@ switch ($action) {
exit;
}
if ($type === 'videotheque') {
// DVDCover API pour vidéothèque
if ($type === 'videotheque') {
$format = $result['format'] ?: 'Blu-ray';
$dcData = fetchDVDCover($titleForSearch, $result['year'], $format);
$dcData = fetchFanartTv($titleForSearch, $result['year'], $format, $pdo);
if (!empty($dcData)) {
if (!empty($dcData['poster'])) $result['poster'] = $dcData['poster'];
if (!empty($dcData['title'])) $result['title'] = $dcData['title'];
@@ -503,14 +474,13 @@ 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 : DVDCover API pour la jaquette
if (empty($data['poster']) && !empty($data['title'])) {
$format = $data['format'] ?: 'Blu-ray';
$dcData = fetchDVDCover($data['title'], $data['year'] ?? '', $format);
if (!empty($dcData['poster'])) {
$data['poster'] = $dcData['poster'];
}
if (empty($data['poster']) && !empty($data['title'])) {
$format = $data['format'] ?: 'Blu-ray';
$dcData = fetchFanartTv($data['title'], $data['year'] ?? '', $format, $pdo);
if (!empty($dcData['poster'])) {
$data['poster'] = $dcData['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);
@@ -614,7 +584,7 @@ switch ($action) {
// Récupération jaquette via DVDCover API
$cleanTitleForDC = cleanTitle($title);
if (!empty($cleanTitleForDC)) {
$dcData = fetchDVDCover($cleanTitleForDC, $year, $format);
$dcData = fetchFanartTv($cleanTitleForDC, $year, $format, $pdo);
if (!empty($dcData)) {
if (!empty($dcData['poster'])) {
$poster = $dcData['poster'];