Auto commit: 2026-02-18T23:19:00.580Z

This commit is contained in:
Flatlogic Bot 2026-02-18 23:19:00 +00:00
parent 1840105cf9
commit 2b84812642
4 changed files with 161 additions and 12 deletions

View File

@ -60,6 +60,27 @@ $requests_today = $stmt->fetchColumn();
</div> </div>
</div> </div>
<div class="row mb-4">
<div class="col-md-12">
<div class="card p-3 border-success" style="background: rgba(37, 211, 102, 0.1);">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div class="d-flex align-items-center">
<div class="bg-success p-3 rounded-circle me-3 shadow-lg">
<i class="bi bi-whatsapp fs-3 text-white"></i>
</div>
<div>
<h5 class="mb-0">Comunidad WhatsApp de Lili Records</h5>
<p class="mb-0 text-secondary small">Monitorea y comparte anuncios directamente en el grupo oficial.</p>
</div>
</div>
<a href="https://chat.whatsapp.com/DkG96pTzAFO3hvLqmzwmTY" target="_blank" class="btn btn-success d-flex align-items-center gap-2">
<i class="bi bi-box-arrow-up-right"></i> IR AL GRUPO DE WHATSAPP
</a>
</div>
</div>
</div>
</div>
<!-- Now Playing Header --> <!-- Now Playing Header -->
<div class="row mb-4"> <div class="row mb-4">
<div class="col-md-12"> <div class="col-md-12">
@ -254,6 +275,7 @@ $requests_today = $stmt->fetchColumn();
<th>Artista</th> <th>Artista</th>
<th>Canción</th> <th>Canción</th>
<th>Solicitado por</th> <th>Solicitado por</th>
<th>Vía</th>
<th>Fecha</th> <th>Fecha</th>
<th>Estado</th> <th>Estado</th>
<th>Acciones</th> <th>Acciones</th>
@ -261,7 +283,7 @@ $requests_today = $stmt->fetchColumn();
</thead> </thead>
<tbody id="requests-body"> <tbody id="requests-body">
<tr> <tr>
<td colspan="6" class="text-center text-secondary">Cargando peticiones...</td> <td colspan="7" class="text-center text-secondary">Cargando peticiones...</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -353,13 +375,18 @@ $requests_today = $stmt->fetchColumn();
if (data.success) { if (data.success) {
const tbody = document.getElementById('requests-body'); const tbody = document.getElementById('requests-body');
if (data.requests.length === 0) { if (data.requests.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-secondary">No hay peticiones pendientes</td></tr>'; tbody.innerHTML = '<tr><td colspan="7" class="text-center text-secondary">No hay peticiones pendientes</td></tr>';
} else { } else {
tbody.innerHTML = data.requests.map(req => ` tbody.innerHTML = data.requests.map(req => `
<tr> <tr class="${req.source === 'whatsapp' ? 'table-success' : ''}" style="${req.source === 'whatsapp' ? 'background: rgba(37, 211, 102, 0.1) !important;' : ''}">
<td>${req.artist}</td> <td>${req.artist}</td>
<td>${req.song}</td> <td>${req.song}</td>
<td>${req.requester}</td> <td>${req.requester}</td>
<td>
${req.source === 'whatsapp'
? '<span class="badge bg-success"><i class="bi bi-whatsapp"></i> WhatsApp</span>'
: '<span class="badge bg-secondary"><i class="bi bi-globe"></i> Web</span>'}
</td>
<td>${new Date(req.created_at).toLocaleString()}</td> <td>${new Date(req.created_at).toLocaleString()}</td>
<td><span class="badge bg-warning text-dark">${req.status}</span></td> <td><span class="badge bg-warning text-dark">${req.status}</span></td>
<td> <td>

View File

@ -34,6 +34,18 @@ if ($method === 'GET') {
db()->query("DELETE FROM messages WHERE created_at < DATE_SUB(NOW(), INTERVAL 6 HOUR)"); db()->query("DELETE FROM messages WHERE created_at < DATE_SUB(NOW(), INTERVAL 6 HOUR)");
// Obtener el Oyente de la Semana (Top 1)
$topStmt = db()->query("
SELECT requester
FROM song_requests
WHERE requester IS NOT NULL AND requester != '' AND requester != 'Anónimo'
AND created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY requester
ORDER BY COUNT(*) DESC
LIMIT 1
");
$topRequester = $topStmt->fetchColumn();
$stmt = db()->prepare("SELECT m.*, f.points, f.is_fan_of_month FROM messages m LEFT JOIN fans f ON m.username = f.name ORDER BY m.created_at DESC LIMIT 50"); $stmt = db()->prepare("SELECT m.*, f.points, f.is_fan_of_month FROM messages m LEFT JOIN fans f ON m.username = f.name ORDER BY m.created_at DESC LIMIT 50");
$stmt->execute(); $stmt->execute();
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
@ -43,7 +55,11 @@ if ($method === 'GET') {
$msg['level_color'] = '#94a3b8'; $msg['level_color'] = '#94a3b8';
$msg['level_emoji'] = ''; $msg['level_emoji'] = '';
if ($msg['is_fan_of_month']) { if ($msg['username'] === $topRequester) {
$msg['level_color'] = '#facc15';
$msg['level_emoji'] = '👑';
$msg['is_top_listener'] = true;
} elseif ($msg['is_fan_of_month']) {
$msg['level_color'] = '#facc15'; $msg['level_color'] = '#facc15';
} elseif ($points >= 2500) { } elseif ($points >= 2500) {
$msg['level_color'] = '#a855f7'; $msg['level_color'] = '#a855f7';

View File

@ -36,6 +36,7 @@ if ($method === 'POST') {
$artist = trim($_POST['artist'] ?? ''); $artist = trim($_POST['artist'] ?? '');
$song = trim($_POST['song'] ?? ''); $song = trim($_POST['song'] ?? '');
$requester = trim($_POST['requester'] ?? 'Anónimo'); $requester = trim($_POST['requester'] ?? 'Anónimo');
$source = trim($_POST['source'] ?? 'web');
if (empty($artist) || empty($song)) { if (empty($artist) || empty($song)) {
echo json_encode(['success' => false, 'error' => 'Falta artista o canción']); echo json_encode(['success' => false, 'error' => 'Falta artista o canción']);
@ -43,8 +44,8 @@ if ($method === 'POST') {
} }
try { try {
$stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester) VALUES (?, ?, ?)"); $stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester, source) VALUES (?, ?, ?, ?)");
$stmt->execute([$artist, $song, $requester]); $stmt->execute([$artist, $song, $requester, $source]);
// Award points for song request // Award points for song request
if ($requester !== 'Anónimo') { if ($requester !== 'Anónimo') {

117
index.php
View File

@ -1577,6 +1577,51 @@ $twitter_link = "https://twitter.com/";
.chat-msg-item.is-me .chat-msg-time { .chat-msg-item.is-me .chat-msg-time {
text-align: left; text-align: left;
} }
/* Top Listener Banner */
.top-listener-banner {
background: linear-gradient(135deg, rgba(250, 204, 21, 0.2), rgba(245, 158, 11, 0.3));
border: 1px solid rgba(250, 204, 21, 0.4);
border-radius: 16px;
padding: 10px 15px;
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 12px;
animation: fadeIn 0.8s ease;
position: relative;
overflow: hidden;
}
.top-listener-banner::after {
content: "";
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.1), transparent);
transform: rotate(25deg);
animation: modal-shine 6s infinite;
pointer-events: none;
}
.top-listener-crown {
font-size: 1.5rem;
color: #facc15;
filter: drop-shadow(0 0 5px rgba(250, 204, 21, 0.5));
}
.top-listener-name {
font-weight: 800;
color: #fff;
font-size: 0.9rem;
}
.top-listener-label {
font-size: 0.65rem;
font-weight: 800;
color: #facc15;
letter-spacing: 1px;
text-transform: uppercase;
display: block;
}
</style> </style>
</head> </head>
<body> <body>
@ -1623,6 +1668,22 @@ $twitter_link = "https://twitter.com/";
</header> </header>
<div class="radio-player"> <div class="radio-player">
<!-- Top Listener of the Week Banner -->
<div id="top-listener-section" style="display: none;">
<div class="top-listener-banner">
<div class="top-listener-crown">
<i class="bi bi-crown-fill"></i>
</div>
<div style="flex: 1;">
<span class="top-listener-label">Oyente de la Semana</span>
<div id="top-listener-display" class="top-listener-name">Cargando...</div>
</div>
<div style="font-size: 0.7rem; opacity: 0.6; font-weight: 700; text-transform: uppercase;">
<i class="bi bi-graph-up-arrow"></i> #1 Ranking
</div>
</div>
</div>
<div class="visualizer-container"> <div class="visualizer-container">
<div id="audio-visualizer" class="audio-visualizer"></div> <div id="audio-visualizer" class="audio-visualizer"></div>
</div> </div>
@ -2861,12 +2922,35 @@ $twitter_link = "https://twitter.com/";
btn.innerHTML = '<i class="bi bi-check-circle-fill"></i> ¡PEDIDA!'; btn.innerHTML = '<i class="bi bi-check-circle-fill"></i> ¡PEDIDA!';
btn.style.backgroundColor = 'var(--accent-color)'; btn.style.backgroundColor = 'var(--accent-color)';
confetti({ // Celebration if the user is #1
particleCount: 50, if (result.is_top) {
spread: 60, confetti({
origin: { y: 0.8 }, particleCount: 200,
colors: ['#38bdf8', '#00e676'] spread: 90,
}); origin: { y: 0.7 },
colors: ['#facc15', '#ffffff', '#38bdf8']
});
// Show special shoutout
const shoutoutModal = document.getElementById('shoutout-modal');
const shoutoutTarget = document.getElementById('shoutout-target');
const shoutoutMsg = document.getElementById('shoutout-message');
shoutoutTarget.innerText = `¡FELICIDADES ${result.top_name.toUpperCase()}!`;
shoutoutMsg.innerText = `¡Te has convertido en el Oyente #1 de la Semana! Gracias por tu increíble apoyo a Lili Records Radio. 👑📻`;
shoutoutModal.style.display = 'flex';
setTimeout(() => shoutoutModal.classList.add('show'), 10);
fetchTopListener(); // Update banner
} else {
confetti({
particleCount: 50,
spread: 60,
origin: { y: 0.8 },
colors: ['#38bdf8', '#00e676']
});
}
setTimeout(() => { setTimeout(() => {
btn.disabled = false; btn.disabled = false;
@ -3026,6 +3110,23 @@ $twitter_link = "https://twitter.com/";
} }
} }
async function fetchTopListener() {
try {
const response = await fetch('api/get_top_requesters.php');
const result = await response.json();
if (result.success && result.data && result.data.length > 0) {
const top = result.data[0];
const section = document.getElementById('top-listener-section');
const display = document.getElementById('top-listener-display');
display.innerHTML = `${top.requester} <span style="opacity: 0.7; font-size: 0.7rem; font-weight: 400;">(${top.total_requests} peticiones)</span>`;
section.style.display = 'block';
}
} catch (error) {
console.error('Error fetching top listener:', error);
}
}
// --- Sleep Timer & Upcoming Tracks --- // --- Sleep Timer & Upcoming Tracks ---
let sleepTimeout = null; let sleepTimeout = null;
let sleepInterval = null; let sleepInterval = null;
@ -3527,16 +3628,20 @@ $twitter_link = "https://twitter.com/";
// Update cycles // Update cycles
setInterval(updateMetadata, 30000); setInterval(updateMetadata, 30000);
setInterval(fetchTopSongs, 60000); setInterval(fetchTopSongs, 60000);
setInterval(fetchTopListener, 60000);
setInterval(fetchGallery, 3000); // Frecuencia aumentada para fotos efímeras (5s) setInterval(fetchGallery, 3000); // Frecuencia aumentada para fotos efímeras (5s)
setInterval(fetchLeaderboard, 60000); setInterval(fetchLeaderboard, 60000);
setInterval(fetchUpcomingTracks, 30000); setInterval(fetchUpcomingTracks, 30000);
setInterval(fetchActivePerks, 30000);
// Initial fetch // Initial fetch
updateMetadata(); updateMetadata();
fetchTopSongs(); fetchTopSongs();
fetchTopListener();
fetchGallery(); fetchGallery();
fetchLeaderboard(); fetchLeaderboard();
fetchUpcomingTracks(); fetchUpcomingTracks();
fetchActivePerks();
// Theme Toggle Functionality // Theme Toggle Functionality
function toggleTheme() { function toggleTheme() {