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