diff --git a/api/get_top_fans.php b/api/get_top_fans.php
index 56409bf..5e80f9d 100644
--- a/api/get_top_fans.php
+++ b/api/get_top_fans.php
@@ -5,9 +5,26 @@ header('Content-Type: application/json');
try {
$pdo = db();
- $stmt = $pdo->query("SELECT username, total_likes, custom_color FROM user_likes ORDER BY total_likes DESC LIMIT 5");
+ // Get top fans from the fans table
+ $stmt = $pdo->query("SELECT name as username, points as total_likes, photo, is_fan_of_month FROM fans ORDER BY points DESC LIMIT 5");
$fans = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ // Add badge logic
+ foreach ($fans as &$fan) {
+ $fan['badges'] = [];
+ if ($fan['is_fan_of_month']) {
+ $fan['badges'][] = ['icon' => 'bi-star-fill', 'color' => '#facc15', 'label' => 'Fan del Mes'];
+ }
+ if ($fan['total_likes'] >= 1000) {
+ $fan['badges'][] = ['icon' => 'bi-gem', 'color' => '#38bdf8', 'label' => 'Diamante'];
+ } elseif ($fan['total_likes'] >= 500) {
+ $fan['badges'][] = ['icon' => 'bi-shield-check', 'color' => '#00c853', 'label' => 'Veterano'];
+ }
+
+ // Custom color fallback
+ $fan['custom_color'] = $fan['is_fan_of_month'] ? '#facc15' : '#38bdf8';
+ }
+
echo json_encode(['success' => true, 'fans' => $fans]);
} catch (Exception $e) {
echo json_encode(['error' => $e->getMessage()]);
diff --git a/api/song_requests.php b/api/song_requests.php
index 3968b37..1fc8e6f 100644
--- a/api/song_requests.php
+++ b/api/song_requests.php
@@ -45,6 +45,21 @@ if ($method === 'POST') {
try {
$stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester) VALUES (?, ?, ?)");
$stmt->execute([$artist, $song, $requester]);
+
+ // Award points for song request
+ if ($requester !== 'Anónimo') {
+ $fanStmt = $db->prepare("SELECT id, points FROM fans WHERE name = ?");
+ $fanStmt->execute([$requester]);
+ $fan = $fanStmt->fetch();
+
+ if ($fan) {
+ $newPoints = $fan['points'] + 25; // More points for a request
+ $db->prepare("UPDATE fans SET points = ? WHERE id = ?")->execute([$newPoints, $fan['id']]);
+ } else {
+ $db->prepare("INSERT INTO fans (name, points) VALUES (?, ?)")->execute([$requester, 25]);
+ }
+ }
+
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
diff --git a/index.php b/index.php
index 0addb94..207d23a 100644
--- a/index.php
+++ b/index.php
@@ -1194,6 +1194,59 @@ $twitter_link = "https://twitter.com/";
opacity: 0.6;
text-transform: uppercase;
}
+
+ /* Leaderboard Styles */
+ .leaderboard-list {
+ display: flex;
+ flex-direction: column;
+ gap: 0.8rem;
+ }
+ .leaderboard-item {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ padding: 0.8rem;
+ border-radius: 16px;
+ transition: all 0.3s ease;
+ }
+ .leaderboard-item:hover {
+ background: rgba(255, 255, 255, 0.1);
+ transform: translateX(5px);
+ border-color: var(--primary-color);
+ }
+ .leaderboard-rank {
+ font-weight: 800;
+ font-size: 1.1rem;
+ width: 25px;
+ text-align: center;
+ color: var(--primary-color);
+ }
+ .leaderboard-avatar {
+ width: 45px;
+ height: 45px;
+ border-radius: 50%;
+ border: 2px solid var(--glass-border);
+ object-fit: cover;
+ }
+ .leaderboard-info {
+ flex: 1;
+ }
+ .leaderboard-name {
+ font-weight: 700;
+ font-size: 0.95rem;
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ }
+ .leaderboard-points {
+ font-size: 0.75rem;
+ opacity: 0.6;
+ }
+ .badge-icon {
+ font-size: 0.8rem;
+ }
@@ -1513,6 +1566,22 @@ $twitter_link = "https://twitter.com/";
+
+
+
+
+
+
+ Suma puntos participando en el chat y pidiendo canciones.
+
+
@@ -2493,11 +2562,35 @@ $twitter_link = "https://twitter.com/";
}
}
- // Fetch Now Playing Metadata from RadioKing
- let progressInterval = null;
-
- async function updateMetadata() {
- // ... (keeping existing logic)
+ async function fetchLeaderboard() {
+ const container = document.getElementById('leaderboard-list');
+ try {
+ const response = await fetch('api/get_top_fans.php');
+ const data = await response.json();
+
+ if (data.success) {
+ if (data.fans.length === 0) {
+ container.innerHTML = 'No hay fans destacados aún.
';
+ return;
+ }
+
+ container.innerHTML = data.fans.map((fan, index) => `
+
+
${index + 1}
+

+
+
+ ${fan.username}
+ ${fan.badges.map(b => ``).join('')}
+
+
${parseInt(fan.total_likes).toLocaleString()} puntos
+
+
+ `).join('');
+ }
+ } catch (error) {
+ container.innerHTML = 'Error al cargar el ranking.
';
+ }
}
async function fetchGallery() {
@@ -2546,18 +2639,27 @@ $twitter_link = "https://twitter.com/";
document.body.style.overflow = 'auto';
}
- // Initial fetch
- fetchGallery();
- setInterval(fetchGallery, 60000); // Update every minute
+ // Fetch Now Playing Metadata
+ let progressInterval = null;
- }
+ async function updateMetadata() {
+ try {
+ const response = await fetch('https://www.radioking.com/widgets/api/v1/radio/828046/track/current');
+ const data = await response.json();
+
+ if (data && data.title) {
+ const title = data.title;
+ const artist = data.artist;
+ const album = data.album || '';
+ const coverUrl = data.cover || './assets/pasted-20260215-163754-def41f49.png';
+ const fullDisplay = `${artist} - ${title}`;
+ if (trackTitle.textContent !== title) {
trackTitle.style.opacity = '0';
if (trackArtist) trackArtist.style.opacity = '0';
if (trackAlbum) trackAlbum.style.opacity = '0';
if (trackCover) trackCover.style.opacity = '0';
- // Reset Like Button
const likeIcon = document.querySelector('#like-song-btn i');
if (likeIcon) {
likeIcon.classList.remove('bi-heart-fill');
@@ -2633,14 +2735,12 @@ $twitter_link = "https://twitter.com/";
if (coverPlaceholder) coverPlaceholder.style.display = 'none';
trackCover.style.opacity = '1';
- // Record History in Database
fetch('api/record_history.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: title, artist: artist, cover: coverUrl })
}).catch(err => console.error("Error recording history:", err));
- // Dynamic Color Extraction
trackCover.onload = function() {
try {
const canvas = document.createElement('canvas');
@@ -2652,13 +2752,11 @@ $twitter_link = "https://twitter.com/";
if (rgb[0] + rgb[1] + rgb[2] > 30) {
const color = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
document.documentElement.style.setProperty('--primary-color', color);
- // Dynamic glow removed for stability
}
} catch(e) {}
};
}
- // Dynamic Background Update
fetch(`api/pexels.php?query=${encodeURIComponent(artist + " " + title + " music background")}`)
.then(res => res.json())
.then(pData => {
@@ -2667,7 +2765,6 @@ $twitter_link = "https://twitter.com/";
}
}).catch(() => {});
- // Progress Bar Logic
const progContainer = document.getElementById('track-progress-container');
const progBar = document.getElementById('track-progress-bar');
@@ -2688,12 +2785,12 @@ $twitter_link = "https://twitter.com/";
}
updateProgressBar();
+ if (progressInterval) clearInterval(progressInterval);
progressInterval = setInterval(updateProgressBar, 1000);
} else if (progContainer) {
progContainer.style.display = 'none';
}
- // Fetch likes for this song
try {
const lResp = await fetch(`api/get_likes.php?song_title=${encodeURIComponent(fullDisplay)}`);
const lData = await lResp.json();
@@ -2702,13 +2799,11 @@ $twitter_link = "https://twitter.com/";
}
} catch (e) {}
- // Check if scrolling is needed
if (trackTitle.scrollWidth > trackTitle.clientWidth) {
trackTitle.classList.add('scrolling');
trackTitle.innerHTML = `${title} ${title} `;
}
- // Update Sticky Bar
const stickyBar = document.getElementById('sticky-now-playing');
const stickyCover = document.getElementById('sticky-track-cover');
const stickyInfo = document.getElementById('sticky-track-info');
@@ -2722,16 +2817,12 @@ $twitter_link = "https://twitter.com/";
document.title = `▶ ${fullDisplay} | Lili Records Radio`;
- // Media Session API for System Controls
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: title,
artist: artist,
album: 'Lili Records Radio',
- artwork: [
- { src: data.cover || './assets/pasted-20260215-163754-def41f49.png', sizes: '512x512', type: 'image/png' },
- { src: data.cover || './assets/pasted-20260215-163754-def41f49.png', sizes: '256x256', type: 'image/png' }
- ]
+ artwork: [{ src: coverUrl, sizes: '512x512', type: 'image/png' }]
});
}
} else {
@@ -2745,13 +2836,17 @@ $twitter_link = "https://twitter.com/";
}
}
- // Update every 30 seconds
+ // Initial fetch
updateMetadata();
fetchTopSongs();
- setInterval(() => {
- updateMetadata();
- fetchTopSongs();
- }, 30000);
+ fetchGallery();
+ fetchLeaderboard();
+
+ // Update cycles
+ setInterval(updateMetadata, 30000);
+ setInterval(fetchTopSongs, 60000);
+ setInterval(fetchGallery, 60000);
+ setInterval(fetchLeaderboard, 60000);
// Theme Toggle Functionality
function toggleTheme() {