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; 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) { 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'; 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 ''; return '';
} }
// ── DVDCover.com via API REST WordPress ── function fetchFanartTv($title, $year = '', $format = 'bluray', $pdo = null) {
function fetchDVDCover($title, $year = '', $format = 'bluray') {
if (empty($title)) return null; if (empty($title)) return null;
$cleanTitle = cleanTitle($title); $cleanTitle = cleanTitle($title);
if (empty($cleanTitle)) return null; if (empty($cleanTitle)) return null;
// API REST WordPress de DVDcover // Récupérer la clé API
$searchUrl = "https://www.dvdcover.com/wp-json/wp/v2/posts?search=" . urlencode($cleanTitle) . "&_embed&per_page=10"; $apiKey = getFanartApiKey($pdo);
if (empty($apiKey)) {
// Fallback sur la clé en dur si non configurée
$apiKey = '70f9747dafe9b27f9b14ef80ee0cacc9';
}
$json = httpGet($searchUrl, 10); // Étape 1 : Chercher le film sur TMDB pour obtenir son ID
if (!$json) { $tmdbKey = getTmdbApiKey($pdo);
error_log("DVDCover API: Échec requête pour '$title'"); if (!$tmdbKey) {
error_log("Fanart.tv: Clé TMDB requise pour obtenir l'ID du film");
return null; return null;
} }
$posts = json_decode($json, true); $searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$tmdbKey}&query=" . urlencode($cleanTitle);
if (!is_array($posts) || empty($posts)) { if (!empty($year)) {
error_log("DVDCover API: Aucun résultat pour '$title'"); $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; return null;
} }
$cleanTitleLower = strtolower($cleanTitle); $tmdbId = $searchData['results'][0]['id'];
$bestPost = null;
$bestScore = 0;
foreach ($posts as $post) { // Étape 2 : Récupérer les artworks depuis fanart.tv
$postTitle = $post['title']['rendered'] ?? ''; $fanartUrl = "https://webservice.fanart.tv/v3/movies/{$tmdbId}?api_key={$apiKey}";
$postTitleLower = strtolower($postTitle); $fanartRes = httpGet($fanartUrl, 5);
$fanartData = $fanartRes ? json_decode($fanartRes, true) : [];
$score = 0; if (isset($fanartData['error'])) {
if (strpos($postTitleLower, $cleanTitleLower) !== false) { error_log("Fanart.tv: Erreur API - " . $fanartData['error']);
$score += 50; return null;
}
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 (!$bestPost && !empty($posts)) {
$bestPost = $posts[0];
}
if (!$bestPost) return null;
// Extraire l'image du post
$poster = ''; $poster = '';
// Méthode 1 : Image mise en avant (_embedded.wp:featuredmedia) // Priorité aux movieposter (jaquettes complètes)
if (isset($bestPost['_embedded']['wp:featuredmedia'][0])) { if (!empty($fanartData['movieposter'])) {
$featured = $bestPost['_embedded']['wp:featuredmedia'][0]; // Filtrer par langue (fr d'abord, puis en, puis tout)
if (!empty($featured['media_details']['sizes'])) { $posters = $fanartData['movieposter'];
$sizes = $featured['media_details']['sizes']; $preferredLangs = ['fr', 'en', ''];
$preferredSizes = ['full', 'large', 'medium', 'thumbnail'];
foreach ($preferredSizes as $size) { foreach ($preferredLangs as $lang) {
if (isset($sizes[$size]['source_url'])) { $filtered = array_filter($posters, function($p) use ($lang) {
$poster = $sizes[$size]['source_url']; return ($lang === '' || ($p['lang'] ?? '') === $lang);
break; });
}
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 // Fallback sur hdmovielogo si pas de movieposter
if (empty($poster) && !empty($bestPost['content']['rendered'])) { if (empty($poster) && !empty($fanartData['hdmovielogo'])) {
$content = $bestPost['content']['rendered']; $logos = $fanartData['hdmovielogo'];
if (preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) { $poster = $logos[0]['url'];
foreach ($matches[1] as $img) { }
if (strpos($img, 'logo') === false &&
strpos($img, 'icon') === false && // Fallback sur moviebackground
strpos($img, 'banner') === false && if (empty($poster) && !empty($fanartData['moviebackground'])) {
strpos($img, 'bg') === false && $backgrounds = $fanartData['moviebackground'];
strpos($img, 'button') === false && $poster = $backgrounds[0]['url'];
strpos($img, 'social') === false &&
(strpos($img, '.jpg') !== false || strpos($img, '.jpeg') !== false || strpos($img, '.png') !== false || strpos($img, '.webp') !== false)) {
$poster = $img;
break;
}
}
}
} }
if (empty($poster)) { 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; 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 [ return [
'poster' => $poster, 'poster' => $poster,
'title' => $bestPost['title']['rendered'] ?? $cleanTitle, 'title' => $cleanTitle,
'format' => $format, 'format' => $format,
]; ];
} }
@@ -384,23 +344,35 @@ switch ($action) {
case 'get_config_keys': case 'get_config_keys':
checkAuth($pdo); checkAuth($pdo);
$stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name = 'tmdb_api_key'"); $stmt = $pdo->prepare("SELECT key_value FROM config WHERE key_name IN ('tmdb_api_key', 'fanart_api_key')");
$stmt->execute(); $row = $stmt->fetch(); $stmt->execute();
echo json_encode(['tmdb_api_key' => $row ? '••••••••' : '']); $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; break;
case 'save_config': case 'save_config':
checkAuth($pdo); checkAuth($pdo);
$keyName = $data['key_name'] ?? ''; $keyName = $data['key_name'] ?? '';
$keyValue = $data['key_value'] ?? ''; $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 = $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]);
} else { } else {
http_response_code(400); echo json_encode(["error" => "Données invalides."]); http_response_code(400); echo json_encode(["error" => "Données invalides."]);
} }
break; break;
case 'get_films': case 'get_films':
$sql = " $sql = "
@@ -413,7 +385,7 @@ switch ($action) {
"; ";
$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'];
$row['rating'] = ($ratingVal == floor($ratingVal)) ? (int)$ratingVal : $ratingVal; $row['rating'] = ($ratingVal == floor($ratingVal)) ? (int)$ratingVal : $ratingVal;
@@ -456,10 +428,9 @@ switch ($action) {
exit; exit;
} }
if ($type === 'videotheque') { if ($type === 'videotheque') {
// DVDCover API pour vidéothèque
$format = $result['format'] ?: 'Blu-ray'; $format = $result['format'] ?: 'Blu-ray';
$dcData = fetchDVDCover($titleForSearch, $result['year'], $format); $dcData = fetchFanartTv($titleForSearch, $result['year'], $format, $pdo);
if (!empty($dcData)) { if (!empty($dcData)) {
if (!empty($dcData['poster'])) $result['poster'] = $dcData['poster']; if (!empty($dcData['poster'])) $result['poster'] = $dcData['poster'];
if (!empty($dcData['title'])) $result['title'] = $dcData['title']; if (!empty($dcData['title'])) $result['title'] = $dcData['title'];
@@ -503,14 +474,13 @@ switch ($action) {
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$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 {
// Vidéothèque : DVDCover API pour la jaquette if (empty($data['poster']) && !empty($data['title'])) {
if (empty($data['poster']) && !empty($data['title'])) { $format = $data['format'] ?: 'Blu-ray';
$format = $data['format'] ?: 'Blu-ray'; $dcData = fetchFanartTv($data['title'], $data['year'] ?? '', $format, $pdo);
$dcData = fetchDVDCover($data['title'], $data['year'] ?? '', $format); if (!empty($dcData['poster'])) {
if (!empty($dcData['poster'])) { $data['poster'] = $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)"; $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);
@@ -614,7 +584,7 @@ switch ($action) {
// Récupération jaquette via DVDCover API // Récupération jaquette via DVDCover API
$cleanTitleForDC = cleanTitle($title); $cleanTitleForDC = cleanTitle($title);
if (!empty($cleanTitleForDC)) { if (!empty($cleanTitleForDC)) {
$dcData = fetchDVDCover($cleanTitleForDC, $year, $format); $dcData = fetchFanartTv($cleanTitleForDC, $year, $format, $pdo);
if (!empty($dcData)) { if (!empty($dcData)) {
if (!empty($dcData['poster'])) { if (!empty($dcData['poster'])) {
$poster = $dcData['poster']; $poster = $dcData['poster'];