diff --git a/api/automation.php b/api/automation.php
new file mode 100644
index 0000000..03c388b
--- /dev/null
+++ b/api/automation.php
@@ -0,0 +1,36 @@
+query("SELECT COUNT(*) FROM song_requests WHERE status = 'played' AND created_at > DATE_SUB(NOW(), INTERVAL 5 MINUTE)");
+ $hasActive = $stmt->fetchColumn();
+
+ if ($hasActive == 0) {
+ // 2. No active song? Let's take the oldest pending request and "execute" it
+ $stmt = $db->query("SELECT * FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1");
+ $next = $stmt->fetch();
+
+ if ($next) {
+ $stmt = $db->prepare("UPDATE song_requests SET status = 'played' WHERE id = ?");
+ $stmt->execute([$next['id']]);
+
+ // Log automation
+ $db->prepare("INSERT INTO automation_logs (message) VALUES (?)")->execute(["Auto-DJ ejecutó: {$next['artist']} - {$next['song']}"]);
+
+ // Announce in chat
+ $chatMsg = "🤖 [AUTO-DJ] Es el turno de: **{$next['artist']} - {$next['song']}** (Pedido por: **{$next['requester']}**) 🎧🔥";
+ $db->prepare("INSERT INTO messages (username, message, type) VALUES ('Sistema', ?, 'dj_power')")->execute([$chatMsg]);
+
+ echo json_encode(['success' => true, 'action' => 'executed', 'song' => $next['song']]);
+ exit;
+ }
+ }
+
+ echo json_encode(['success' => true, 'action' => 'none']);
+} catch (Exception $e) {
+ echo json_encode(['success' => false, 'error' => $e->getMessage()]);
+}
diff --git a/api/current_song.php b/api/current_song.php
new file mode 100644
index 0000000..533c30d
--- /dev/null
+++ b/api/current_song.php
@@ -0,0 +1,53 @@
+query("SELECT artist, song, requester, youtube_url FROM song_requests WHERE status = 'played' AND created_at > DATE_SUB(NOW(), INTERVAL 4 MINUTE) ORDER BY created_at DESC LIMIT 1");
+ $override = $stmt->fetch();
+
+ if ($override) {
+ echo json_encode([
+ 'success' => true,
+ 'source' => 'local_request',
+ 'artist' => $override['artist'],
+ 'title' => $override['song'],
+ 'requester' => $override['requester'],
+ 'youtube_url' => $override['youtube_url'],
+ 'cover' => './assets/pasted-20260215-163754-def41f49.png'
+ ]);
+ exit;
+ }
+
+ // Fallback: Proxy RadioKing metadata
+ $radioKingUrl = 'https://www.radioking.com/widgets/api/v1/radio/828046/track/current';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $radioKingUrl);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5);
+ $resp = curl_exec($ch);
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+ if ($httpCode === 200 && $resp) {
+ $data = json_decode($resp, true);
+ echo json_encode([
+ 'success' => true,
+ 'source' => 'radioking',
+ 'artist' => $data['artist'] ?? 'Lili Records',
+ 'title' => $data['title'] ?? 'La mejor música',
+ 'cover' => $data['cover'] ?? './assets/pasted-20260215-163754-def41f49.png',
+ 'duration' => $data['duration'] ?? 0,
+ 'end_at' => $data['end_at'] ?? null,
+ 'next_track' => $data['next_track'] ?? null
+ ]);
+ } else {
+ echo json_encode(['success' => false, 'error' => 'Failed to fetch RadioKing metadata']);
+ }
+} catch (Exception $e) {
+ echo json_encode(['success' => false, 'error' => $e->getMessage()]);
+}
diff --git a/api/song_requests.php b/api/song_requests.php
index 3b4165c..82b3126 100644
--- a/api/song_requests.php
+++ b/api/song_requests.php
@@ -70,8 +70,54 @@ if ($method === 'POST') {
}
try {
- $stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester, source) VALUES (?, ?, ?, ?)");
- $stmt->execute([$artist, $song, $requester, $source]);
+ // Auto-DJ: Check if we should "execute" this song immediately
+ // If there's no song marked as 'played' in the last 5 minutes, we execute this one automatically
+ $checkStmt = $db->query("SELECT COUNT(*) FROM song_requests WHERE status = 'played' AND created_at > DATE_SUB(NOW(), INTERVAL 5 MINUTE)");
+ $activePlayed = $checkStmt->fetchColumn();
+
+ $initialStatus = 'pending';
+ $wasAutoExecuted = false;
+
+ if ($activePlayed == 0) {
+ $initialStatus = 'played';
+ $wasAutoExecuted = true;
+ }
+
+ $stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester, source, status) VALUES (?, ?, ?, ?, ?)");
+ $stmt->execute([$artist, $song, $requester, $source, $initialStatus]);
+
+ if ($wasAutoExecuted) {
+ // Try to find a YouTube link for the song using AI
+ $youtubeUrl = null;
+ try {
+ require_once __DIR__ . '/../ai/LocalAIApi.php';
+ $aiResp = LocalAIApi::createResponse([
+ 'input' => [
+ ['role' => 'system', 'content' => 'Eres un asistente de radio. Tu tarea es encontrar el ID de YouTube oficial para una canción. Responde ÚNICAMENTE con el ID del video (ej: dQw4w9WgXcQ). Si no estás seguro, responde "None".'],
+ ['role' => 'user', 'content' => "Encuentra el ID de YouTube para: $artist - $song"]
+ ]
+ ]);
+ if (!empty($aiResp['success'])) {
+ $id = trim(LocalAIApi::extractText($aiResp));
+ if ($id !== 'None' && strlen($id) > 5 && strlen($id) < 15) {
+ $youtubeUrl = "https://www.youtube.com/watch?v=$id";
+ }
+ }
+ } catch (Exception $e) {
+ error_log("AI YouTube search failed: " . $e->getMessage());
+ }
+
+ $stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester, source, status, youtube_url) VALUES (?, ?, ?, ?, ?, ?)");
+ $stmt->execute([$artist, $song, $requester, $source, $initialStatus, $youtubeUrl]);
+
+ // Announce auto-execution
+ $chatMsg = "🚀 [AUTO-DJ] ¡Petición de **$requester** ejecutada automáticamente! 🎶 Sonando: **$artist - $song**" . ($youtubeUrl ? " (con video)" : "");
+ $db->prepare("INSERT INTO messages (username, message, type) VALUES ('Sistema', ?, 'dj_power')")->execute([$chatMsg]);
+ } else {
+ $stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester, source, status) VALUES (?, ?, ?, ?, ?)");
+ $stmt->execute([$artist, $song, $requester, $source, $initialStatus]);
+ }
+
// Award points for song request
if ($requester !== 'Anónimo') {
diff --git a/index.php b/index.php
index d1bc600..c467b46 100644
--- a/index.php
+++ b/index.php
@@ -3588,11 +3588,23 @@ $twitter_link = "https://twitter.com/";
}
}
- // Initial fetch and poll
- fetchMessages();
- updatePhotoCounter();
- setInterval(fetchMessages, 3000);
- setInterval(updatePhotoCounter, 30000); // Check limit status every 30s
+ async function checkAutomation() {
+ try {
+ const response = await fetch('api/automation.php');
+ const data = await response.json();
+ if (data.success && data.action === 'executed') {
+ // Force metadata update if something was executed
+ updateMetadata();
+ if (typeof fetchSongRequests === 'function') fetchSongRequests();
+ }
+ } catch (error) {
+ console.error('Automation error:', error);
+ }
+ }
+
+ // Run automation check every 15 seconds
+ setInterval(checkAutomation, 15000);
+ setTimeout(checkAutomation, 2000); // Initial check
// --- End Chat Functionality ---
// --- Song Request Functionality ---
@@ -4435,7 +4447,7 @@ $twitter_link = "https://twitter.com/";
async function updateMetadata() {
try {
- const response = await fetch('https://www.radioking.com/widgets/api/v1/radio/828046/track/current');
+ const response = await fetch('api/current_song.php');
const data = await response.json();
if (data && data.title) {
@@ -4444,8 +4456,34 @@ $twitter_link = "https://twitter.com/";
const album = data.album || '';
const coverUrl = data.cover || './assets/pasted-20260215-163754-def41f49.png';
const fullDisplay = `${artist} - ${title}`;
+ const source = data.source || 'radioking';
+ const requester = data.requester || '';
if (trackTitle.textContent !== title) {
+ // If it's a local request, show special label
+ const label = document.querySelector('.track-label');
+ if (source === 'local_request') {
+ label.innerHTML = `PETICIÓN DE ${requester.toUpperCase()}:`;
+ label.style.animation = 'pulse 1s infinite';
+ if (data.youtube_url) {
+ const youtubeBtn = document.createElement('a');
+ youtubeBtn.href = data.youtube_url;
+ youtubeBtn.target = '_blank';
+ youtubeBtn.style.background = '#ff0000';
+ youtubeBtn.style.color = '#fff';
+ youtubeBtn.style.padding = '4px 10px';
+ youtubeBtn.style.borderRadius = '12px';
+ youtubeBtn.style.fontSize = '0.65rem';
+ youtubeBtn.style.fontWeight = '800';
+ youtubeBtn.style.textDecoration = 'none';
+ youtubeBtn.style.marginLeft = '10px';
+ youtubeBtn.innerHTML = ' VER VIDEO';
+ label.appendChild(youtubeBtn);
+ }
+ } else {
+ label.innerText = 'ESTÁS ESCUCHANDO:';
+ label.style.animation = 'none';
+ }
trackTitle.style.opacity = '0';
if (trackArtist) trackArtist.style.opacity = '0';
if (trackAlbum) trackAlbum.style.opacity = '0';