Nom personnalisé] if (!defined('PRIORITY_CATEGORIES')) { define('PRIORITY_CATEGORIES', [ 11 => 'Actualité & Politique', // News & Politique 14 => 'Activisme', // Activism 1 => 'Musique', // Musique ]); } // ========================================= // Configuration Mastodon // ========================================= if (!defined('MASTODON_INSTANCE_URL')) define('MASTODON_INSTANCE_URL', 'https://mamot.fr'); if (!defined('MASTODON_DATE_FORMAT')) define('MASTODON_DATE_FORMAT', 'fr-FR'); if (!defined('MASTODON_BTN_SEE_MORE')) define('MASTODON_BTN_SEE_MORE', 'Voir plus de post'); if (!defined('MASTODON_BTN_RELOAD')) define('MASTODON_BTN_RELOAD', 'Rafraichir'); if (!defined('MASTODON_MAX_POST_FETCH')) define('MASTODON_MAX_POST_FETCH', '10'); if (!defined('MASTODON_MAX_POST_SHOW')) define('MASTODON_MAX_POST_SHOW', '10'); // Informations du site if (!defined('SITE_NAME')) define('SITE_NAME', 'Kaubuntu.re'); if (!defined('SITE_DESCRIPTION')) define('SITE_DESCRIPTION', 'Votre plateforme de médias libres'); if (!defined('SITE_LOGO')) define('SITE_LOGO', 'img/logo.png'); if (!defined('SITE_FAVICON')) define('SITE_FAVICON', 'img/favicon.png'); // Réseaux sociaux if (!defined('FACEBOOK_URL')) define('FACEBOOK_URL', '#'); if (!defined('X_URL')) define('X_URL', '#'); if (!defined('INSTAGRAM_URL')) define('INSTAGRAM_URL', '#'); if (!defined('YOUTUBE_URL')) define('YOUTUBE_URL', '#'); if (!defined('TIKTOK_URL')) define('TIKTOK_URL', '#'); // Contacts if (!defined('CONTACT_EMAIL')) define('CONTACT_EMAIL', 'contact@kaubuntu.re'); // Fonctionnalités define('ENABLE_SEARCH', true); if (!defined('ENABLE_USER_ACCOUNTS')) define('ENABLE_USER_ACCOUNTS', false); // Cache if (!defined('CACHE_ENABLED')) define('CACHE_ENABLED', false); if (!defined('CACHE_DURATION')) define('CACHE_DURATION', 3600); // En secondes (1 heure) // Tags pour filtrer les vidéos selon les catégories if (!defined('TAG_SHORT')) define('TAG_SHORT', 'short'); // Locale et fuseau horaire setlocale(LC_TIME, 'fr_FR.UTF-8'); date_default_timezone_set('Indian/Reunion'); // Initialisation des catégories de vidéo depuis l'API $peertube_categories = initCategories(); define('PEERTUBE_CATEGORIES', $peertube_categories); /** * Initialise et récupère les catégories depuis l'API PeerTube * * @return array Liste des catégories */ function initCategories() { // Récupérer la liste des catégories depuis l'API $categories = callPeerTubeApi('videos/categories'); $result = []; foreach ($categories as $key => $name) { $result[$key] = $name; } return $result; } /** * Fonction utilitaire pour appeler l'API PeerTube * * @param string $endpoint Point de terminaison de l'API * @param array $params Paramètres optionnels pour la requête * @return array Données retournées par l'API */ function callPeerTubeApi($endpoint, $params = []) { $url = PEERTUBE_URL . '/api/v1/' . $endpoint; // Ajouter les paramètres à l'URL if (!empty($params)) { $url .= '?' . http_build_query($params); } // Initialiser cURL $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Ajouter la clé API si définie if (defined('API_KEY') && !empty(API_KEY)) { curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: ApiKey ' . API_KEY ]); } // Exécuter la requête $response = curl_exec($ch); curl_close($ch); // Traiter la réponse if ($response === false) { // En cas d'erreur, retourner un tableau vide return []; } // Décoder la réponse JSON $data = json_decode($response, true); return $data ?: []; } /** * Récupère les catégories depuis l'API PeerTube * * @return array Liste des catégories */ function getCategories() { // Utiliser les catégories déjà récupérées $categories = PEERTUBE_CATEGORIES; $result = []; foreach ($categories as $key => $name) { $result[] = [ 'id' => $key, 'name' => $name ]; } return $result; } /** * Récupère les vidéos récentes depuis l'API PeerTube * * @param int $count Nombre de vidéos à récupérer * @return array Liste des vidéos récentes */ function getRecentVideos($count = RECENT_VIDEOS_COUNT) { // Récupérer les vidéos récentes $data = callPeerTubeApi('videos', [ 'sort' => '-publishedAt', 'count' => $count, 'isLocal' => true ]); return formatVideosData($data['data'] ?? []); } /** * Récupère les vidéos tendances depuis l'API PeerTube * * @param int $count Nombre de vidéos à récupérer * @return array Liste des vidéos tendances */ function getTrendingVideos($count = TRENDING_VIDEOS_COUNT) { // Récupérer les vidéos tendances $data = callPeerTubeApi('videos', [ 'sort' => '-trending', 'count' => $count, 'isLocal' => true ]); return formatVideosData($data['data'] ?? []); } /** * Récupère les vidéos avec un tag spécifique depuis l'API PeerTube * * @param string $tag Tag à filtrer * @param int $count Nombre de vidéos à récupérer * @return array Liste des vidéos */ function getVideosByTag($tag, $count) { // Récupérer les vidéos par tag $data = callPeerTubeApi('videos', [ 'tagsOneOf' => $tag, 'count' => $count, 'isLocal' => true ]); return formatVideosData($data['data'] ?? []); } /** * Récupère les shorts (vidéos courtes) depuis l'API PeerTube * Les shorts sont des vidéos locales de moins de 2 minutes * * @param int $count Nombre de shorts à récupérer * @return array Liste des shorts */ function getShorts($count = SHORTS_COUNT) { // Récupérer plus de vidéos que nécessaire pour pouvoir filtrer $data = callPeerTubeApi('videos', [ 'sort' => '-publishedAt', // Les plus récentes d'abord 'count' => $count * 3, // Récupérer plus de vidéos pour pouvoir filtrer 'isLocal' => true ]); // Formater les données $allVideos = formatVideosData($data['data'] ?? []); // Filtrer pour ne garder que les vidéos de moins de 2 minutes (120 secondes) et en mode portrait $shortVideos = array_filter($allVideos, function($video) { // Vérifier la durée (moins de 2 minutes) $durationOk = $video['duration'] < 120; // Vérifier le ratio (mode portrait) $ratioOk = isset($video['aspectRatio']) && $video['aspectRatio'] <= 1; return $durationOk && $ratioOk; }); // Limiter au nombre demandé return array_slice($shortVideos, 0, $count); } /** * Récupère les vidéos sur l'indépendance depuis l'API PeerTube * * @param int $count Nombre de vidéos à récupérer * @return array Liste des vidéos sur l'indépendance */ function getIndependenceVideos($count = INDEPENDENCE_VIDEOS_COUNT) { // Récupérer les vidéos sur l'indépendance return getVideosByTag(TAG_INDEPENDENCE, $count); } /** * Formate les données brutes des vidéos venant de l'API * * @param array $videosData Données brutes des vidéos * @return array Données formatées */ function formatVideosData($videosData) { $videos = []; foreach ($videosData as $video) { // Récupérer la vignette (thumbnail) $thumbnail = isset($video['previewPath']) ? PEERTUBE_URL . $video['previewPath'] : 'img/default-thumbnail.jpg'; // Récupérer l'avatar de la chaîne $channelAvatar = isset($video['channel']['avatars'][0]['path']) && isset($video['channel']['avatars'][0]['path']) ? PEERTUBE_URL . $video['channel']['avatars'][0]['path'] : 'img/default-avatar.png'; // Formater les données $videos[] = [ 'id' => $video['uuid'], 'title' => $video['name'], 'thumbnail' => $thumbnail, 'duration' => $video['duration'], 'channel' => $video['channel']['displayName'], 'channelAvatar' => $channelAvatar, 'views' => $video['views'], 'date' => $video['publishedAt'], 'aspectRatio' => $video['aspectRatio'], 'description' => $video['description'] ?? '', 'tags' => $video['tags'] ?? [] ]; } return $videos; } // Fonctions utilitaires pour formater les données d'affichage function formatDuration($seconds) { $hours = floor($seconds / 3600); $minutes = floor(($seconds % 3600) / 60); $remainingSeconds = $seconds % 60; if ($hours > 0) { return sprintf('%d:%02d:%02d', $hours, $minutes, $remainingSeconds); } else { return sprintf('%d:%02d', $minutes, $remainingSeconds); } } function formatViewCount($views) { if ($views >= 1000000) { return round($views / 1000000, 1) . 'M'; } elseif ($views >= 1000) { return round($views / 1000, 1) . 'K'; } else { return $views; } } function formatDate($dateString) { $date = new DateTime($dateString); $now = new DateTime(); $interval = $now->diff($date); if ($interval->days == 0) { return 'Aujourd\'hui'; } elseif ($interval->days == 1) { return 'Hier'; } elseif ($interval->days < 7) { return 'Il y a ' . $interval->days . ' jours'; } elseif ($interval->days < 30) { $weeks = floor($interval->days / 7); return 'Il y a ' . $weeks . ' semaine' . ($weeks > 1 ? 's' : ''); } elseif ($interval->days < 365) { $months = floor($interval->days / 30); return 'Il y a ' . $months . ' mois'; } else { $years = floor($interval->days / 365); return 'Il y a ' . $years . ' an' . ($years > 1 ? 's' : ''); } } /** * Récupère les vidéos d'une catégorie spécifique depuis l'API PeerTube * * @param int $categoryId Identifiant de la catégorie * @param int $count Nombre de vidéos à récupérer * @return array Liste des vidéos de la catégorie */ function getVideosByCategory($categoryId, $count = CATEGORY_VIDEOS_COUNT) { // Récupérer les vidéos par catégorie $data = callPeerTubeApi('videos', [ 'categoryOneOf' => $categoryId, 'count' => $count, 'sort' => '-publishedAt', // Les plus récentes d'abord 'isLocal' => true ]); return formatVideosData($data['data'] ?? []); } /** * Récupère la liste des catégories à afficher (triées selon les priorités) * * @return array Liste des catégories avec id, name et videos */ function getDisplayCategories() { $categories = []; $priorityCategories = PRIORITY_CATEGORIES; $allCategories = PEERTUBE_CATEGORIES; // Ajouter uniquement les catégories prioritaires dans l'ordre défini foreach ($priorityCategories as $catId => $categoryName) { $videos = getVideosByCategory($catId); // N'ajouter que les catégories qui ont des vidéos if (!empty($videos)) { $categories[] = [ 'id' => $catId, 'name' => $categoryName, 'videos' => $videos ]; } } return $categories; } ?>