Files
annu-kute-ced/includes/lib/funkwhale.php
T

143 lines
5.3 KiB
PHP

<?php
/**
* Intégration Funkwhale : récupération de morceaux aléatoires via l'API.
*
* Extrait de includes/config.php (ARC-1) — chargé par ce dernier.
* Dépend de lib/http.php (client cURL) et lib/format.php (formatDuration).
*/
/**
* Récupère des morceaux aléatoires depuis Funkwhale via l'API
*
* @param string $funkwhaleUrl URL de l'instance Funkwhale
* @param int $count Nombre de morceaux à récupérer
* @return array Liste des morceaux formatés
*/
function getFunkwhaleTracks($funkwhaleUrl = null, $count = null) {
if (!defined('FUNKWHALE_ENABLED') || !FUNKWHALE_ENABLED) {
return [];
}
$funkwhaleUrl = $funkwhaleUrl ?? FUNKWHALE_URL;
$count = $count ?? FUNKWHALE_TRACKS_COUNT;
// Validation de l'URL Funkwhale pour prévenir SSRF
if (!isValidRemoteUrl($funkwhaleUrl)) {
error_log('SECURITY: Invalid Funkwhale URL detected: ' . $funkwhaleUrl);
return [];
}
// Clé de cache - on récupère un grand nombre de morceaux pour le cache
$cacheKey = 'funkwhale_' . md5($funkwhaleUrl);
$cacheFetchSize = 50; // Nombre de morceaux à mettre en cache
// Vérifier le cache
$allTracks = null;
if (defined('CACHE_ENABLED') && CACHE_ENABLED) {
$allTracks = getFromCache($cacheKey);
}
// Si pas de cache, récupérer depuis l'API
if ($allTracks === null) {
try {
// Construire l'URL de l'API en ordre aléatoire ; le filtrage local
// est fait ensuite côté PHP (comparaison de domaine)
$apiUrl = rtrim($funkwhaleUrl, '/') . '/api/v1/tracks?ordering=random&page_size=' . $cacheFetchSize . '&scope=all';
// Récupérer les morceaux
$response = httpGet($apiUrl, ['timeout' => 10]);
$jsonContent = $response['body'];
if ($response['code'] !== 200 || !$jsonContent) {
return [];
}
// Parser le JSON
$data = json_decode($jsonContent, true);
if (!$data || !isset($data['results'])) {
return [];
}
$allTracks = [];
// Extraire le domaine de l'instance locale pour filtrer
$localDomain = parse_url($funkwhaleUrl, PHP_URL_HOST);
// Parcourir les morceaux et filtrer pour garder uniquement les morceaux locaux
foreach ($data['results'] as $item) {
// Vérifier si le morceau est local en comparant le domaine
// Les morceaux fédérés ont généralement un domaine différent dans leur URL
$isLocal = true;
// Vérifier via l'URL de l'artiste ou de l'album
if (isset($item['artist']['channel'])) {
$artistDomain = parse_url($item['artist']['channel'], PHP_URL_HOST);
if ($artistDomain && $artistDomain !== $localDomain) {
$isLocal = false;
}
}
// Ou vérifier via le champ is_local si disponible
if (isset($item['is_local']) && !$item['is_local']) {
$isLocal = false;
}
// Ne garder que les morceaux locaux
if ($isLocal) {
// Récupérer l'URL d'écoute depuis l'API (peut être relative)
$listenUrl = $item['listen_url'] ?? '';
// Si l'URL est relative, la transformer en URL absolue
if (!empty($listenUrl) && strpos($listenUrl, 'http') !== 0) {
$listenUrl = rtrim($funkwhaleUrl, '/') . $listenUrl;
}
$track = [
'title' => $item['title'] ?? '',
'artist' => $item['artist']['name'] ?? 'Artiste inconnu',
'album' => $item['album']['title'] ?? '',
'cover' => $item['album']['cover']['urls']['medium_square_crop'] ?? '',
'duration' => $item['uploads'][0]['duration'] ?? 0,
'link' => rtrim($funkwhaleUrl, '/') . '/library/tracks/' . ($item['id'] ?? ''),
'trackId' => $item['id'] ?? 0,
'audioUrl' => $listenUrl,
];
// Formater la durée
if ($track['duration']) {
$track['formattedDuration'] = formatDuration($track['duration']);
} else {
$track['formattedDuration'] = '';
}
$allTracks[] = $track;
}
}
// Mettre en cache tous les morceaux locaux
if (defined('CACHE_ENABLED') && CACHE_ENABLED) {
saveToCache($cacheKey, $allTracks);
}
} catch (Exception $e) {
error_log('Erreur lors de la récupération des morceaux Funkwhale: ' . $e->getMessage());
return [];
}
}
// Si pas assez de morceaux, retourner ce qu'on a
if (empty($allTracks)) {
return [];
}
// Sélectionner aléatoirement $count morceaux parmi tous les morceaux en cache
$trackCount = count($allTracks);
if ($trackCount <= $count) {
return $allTracks;
}
// Mélanger et prendre les N premiers
shuffle($allTracks);
return array_slice($allTracks, 0, $count);
}