From 0eb723a087c3ac6ec1101fdd2818cfaf19e8d6ae Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 25 Feb 2026 20:32:07 +0000 Subject: [PATCH] Auto commit: 2026-02-25T20:32:07.364Z --- admin.php | 148 +++++++++++++++++++++++++++++++++++++++--- api/current_song.php | 35 +++++++++- api/song_requests.php | 22 +++++-- index.php | 26 -------- 4 files changed, 189 insertions(+), 42 deletions(-) diff --git a/admin.php b/admin.php index 768ed89..f7ff6e2 100644 --- a/admin.php +++ b/admin.php @@ -183,6 +183,37 @@ $requests_today = $stmt->fetchColumn(); + +
+
+
+
+
Mi Playlist de DJ (Canciones que voy a poner)
+ +
+
+ + + + + + + + + + + + + + +
ArtistaCanciónEstadoAcciones
Cargando mi lista...
+
+
+
+
+
@@ -337,6 +368,34 @@ $requests_today = $stmt->fetchColumn();
+ + + @@ -571,6 +630,7 @@ $requests_today = $stmt->fetchColumn(); const formData = new FormData(); formData.append('id', id); formData.append('action', action); + formData.append('username', 'Admin'); // Added default username for bonus logic try { const response = await fetch('api/song_requests.php', { @@ -579,6 +639,17 @@ $requests_today = $stmt->fetchColumn(); }); const data = await response.json(); if (data.success) { + fetchRequests(); + fetchDjPlaylist(); + fetchStats(); + } else { + alert('Error: ' + data.error); + } + } catch (error) { + alert('Error al procesar la solicitud'); + } + } + function showManualRequestModal() { const modal = new bootstrap.Modal(document.getElementById('manualRequestModal')); modal.show(); @@ -619,15 +690,6 @@ $requests_today = $stmt->fetchColumn(); } } - fetchRequests(); - } else { - alert('Error: ' + data.error); - } - } catch (error) { - alert('Error al procesar la solicitud'); - } - } - async function announceOnAir() { const title = document.getElementById('admin-track-title').innerText.trim(); const artist = document.getElementById('admin-track-artist').innerText.trim(); @@ -736,17 +798,85 @@ $requests_today = $stmt->fetchColumn(); } } + function showDjAddModal() { + const modal = new bootstrap.Modal(document.getElementById('djAddModal')); + modal.show(); + } + + async function submitDjRequest() { + const artist = document.getElementById('dj-artist').value; + const song = document.getElementById('dj-song').value; + + if (!artist || !song) { + alert('Por favor, rellena artista y canción.'); + return; + } + + const formData = new FormData(); + formData.append('requester', 'Lili Records DJ'); + formData.append('artist', artist); + formData.append('song', song); + formData.append('source', 'admin'); + + try { + const response = await fetch('api/song_requests.php', { + method: 'POST', + body: formData + }); + const data = await response.json(); + if (data.success) { + bootstrap.Modal.getInstance(document.getElementById('djAddModal')).hide(); + document.getElementById('dj-add-form').reset(); + fetchDjPlaylist(); + fetchRequests(); + } else { + alert('Error: ' + data.error); + } + } catch (error) { + alert('Error al guardar la canción.'); + } + } + + async function fetchDjPlaylist() { + try { + const response = await fetch('api/song_requests.php?source=admin&status=pending'); + const data = await response.json(); + if (data.success) { + const tbody = document.getElementById('dj-playlist-body'); + if (data.requests.length === 0) { + tbody.innerHTML = 'No tienes canciones en tu lista actual'; + } else { + tbody.innerHTML = data.requests.map(req => ` + + ${req.artist} + ${req.song} + ${req.status} + + + + + + `).join(''); + } + } + } catch (error) { + console.error('Error fetching DJ playlist:', error); + } + } + fetchRequests(); fetchStats(); updateNowPlaying(); fetchAnnouncements(); fetchTopRequesters(); + fetchDjPlaylist(); setInterval(() => { fetchRequests(); fetchStats(); updateNowPlaying(); fetchAnnouncements(); fetchTopRequesters(); + fetchDjPlaylist(); }, 15000); diff --git a/api/current_song.php b/api/current_song.php index a5ba73a..db55f8f 100644 --- a/api/current_song.php +++ b/api/current_song.php @@ -17,11 +17,24 @@ try { if ($remaining > 0) { // Find next track for local requests - $stmtNext = $db->query("SELECT artist, song FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1"); + $stmtNext = $db->query("SELECT id, artist, song FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1"); $nextTrack = $stmtNext->fetch(); $nextInfo = null; if ($nextTrack) { $nextInfo = ['artist' => $nextTrack['artist'], 'title' => $nextTrack['song']]; + + // Server-side warning logic: if 30s left and warning not sent + if ($remaining <= 35 && $remaining > 15) { + $stmtCheck = $db->prepare("SELECT warning_sent FROM song_requests WHERE id = ?"); + $stmtCheck->execute([$nextTrack['id']]); + $wSent = $stmtCheck->fetchColumn(); + + if (!$wSent) { + $chatMsg = "⏭️ **Próxima canción:** {$nextTrack['artist']} - {$nextTrack['song']} 🎶 (en 30 seg aprox)"; + $db->prepare("INSERT INTO messages (username, message, type) VALUES ('Sistema', ?, 'dj_power')")->execute([$chatMsg]); + $db->prepare("UPDATE song_requests SET warning_sent = 1 WHERE id = ?")->execute([$nextTrack['id']]); + } + } } echo json_encode([ @@ -60,11 +73,29 @@ try { if ($endAt && $duration) { $startedAt = date('c', strtotime($endAt) - $duration); + $remainingRadio = strtotime($endAt) - time(); + + // If RadioKing song has ~30s left and there's a local pending request + if ($remainingRadio <= 35 && $remainingRadio > 15) { + $stmtNext = $db->query("SELECT id, artist, song FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1"); + $localNext = $stmtNext->fetch(); + if ($localNext) { + $stmtCheck = $db->prepare("SELECT warning_sent FROM song_requests WHERE id = ?"); + $stmtCheck->execute([$localNext['id']]); + $wSent = $stmtCheck->fetchColumn(); + + if (!$wSent) { + $chatMsg = "⏭️ **Próxima canción:** {$localNext['artist']} - {$localNext['song']} 🎶 (en 30 seg aprox)"; + $db->prepare("INSERT INTO messages (username, message, type) VALUES ('Sistema', ?, 'dj_power')")->execute([$chatMsg]); + $db->prepare("UPDATE song_requests SET warning_sent = 1 WHERE id = ?")->execute([$localNext['id']]); + } + } + } } // For RadioKing source, check if there's a pending local request (it will be next) $nextInfo = $data['next_track'] ?? null; - $stmtNext = $db->query("SELECT artist, song FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1"); + $stmtNext = $db->query("SELECT id, artist, song FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1"); $localNext = $stmtNext->fetch(); if ($localNext) { $nextInfo = ['artist' => $localNext['artist'], 'title' => $localNext['song']]; diff --git a/api/song_requests.php b/api/song_requests.php index 85584d0..fcc6f16 100644 --- a/api/song_requests.php +++ b/api/song_requests.php @@ -224,15 +224,27 @@ if ($method === 'GET') { $db->query("UPDATE song_requests SET status = 'played' WHERE status = 'pending' AND created_at < (NOW() - INTERVAL 2 HOUR)"); $status = $_GET['status'] ?? 'pending'; + $source = $_GET['source'] ?? null; $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10; - if ($status === 'all') { - $stmt = $db->query("SELECT * FROM song_requests ORDER BY is_priority DESC, created_at DESC LIMIT $limit"); - } else { - $stmt = $db->prepare("SELECT * FROM song_requests WHERE status = ? ORDER BY is_priority DESC, created_at DESC LIMIT $limit"); - $stmt->execute([$status]); + $query = "SELECT * FROM song_requests WHERE 1=1"; + $params = []; + + if ($status !== 'all') { + $query .= " AND status = ?"; + $params[] = $status; } + if ($source) { + $query .= " AND source = ?"; + $params[] = $source; + } + + $query .= " ORDER BY is_priority DESC, created_at DESC LIMIT $limit"; + + $stmt = $db->prepare($query); + $stmt->execute($params); + $requests = $stmt->fetchAll(); echo json_encode(['success' => true, 'requests' => $requests]); } catch (Exception $e) { diff --git a/index.php b/index.php index 2abe393..5a56c29 100644 --- a/index.php +++ b/index.php @@ -4444,7 +4444,6 @@ $twitter_link = "https://twitter.com/"; // Fetch Now Playing Metadata let progressInterval = null; - let nextSongNoticeSent = false; let currentTrackId = ''; async function updateMetadata() { @@ -4462,7 +4461,6 @@ $twitter_link = "https://twitter.com/"; const requester = data.requester || ''; if (trackTitle.textContent !== title) { - nextSongNoticeSent = false; currentTrackId = fullDisplay; // If it's a local request, show special label const label = document.querySelector('.track-label'); @@ -4625,30 +4623,6 @@ $twitter_link = "https://twitter.com/"; const now = new Date().getTime(); const elapsed = now - start; - // Check if we should send next song notice (approx 30s before end) - const remainingSec = Math.floor((end - now) / 1000); - if (remainingSec <= 30 && remainingSec > 25 && !nextSongNoticeSent && data.next_track) { - nextSongNoticeSent = true; - let nextLabel = ""; - if (typeof data.next_track === 'object') { - const nextArtist = data.next_track.artist || 'Artista'; - const nextTitle = data.next_track.title || 'Título'; - nextLabel = `${nextArtist} - ${nextTitle}`; - } else { - nextLabel = data.next_track; - } - const nextMsg = `⏭️ **Próxima canción:** ${nextLabel} 🎶`; - fetch('api/chat.php', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - username: 'Sistema', - message: nextMsg, - type: 'dj_power' - }) - }).catch(err => console.error('Error sending next track notice:', err)); - } - let percent = (elapsed / duration) * 100; if (percent > 100) percent = 100; if (percent < 0) percent = 0;