Auto commit: 2026-02-25T19:30:52.555Z
This commit is contained in:
parent
6b0e285541
commit
2e5c1af7eb
36
api/automation.php
Normal file
36
api/automation.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
|
||||
// 1. Check if there is an active "played" song within its duration (e.g. 5 minutes)
|
||||
$stmt = $db->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()]);
|
||||
}
|
||||
53
api/current_song.php
Normal file
53
api/current_song.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
|
||||
// Check for a "manual override" song that was recently marked as played
|
||||
// We look for a song marked as 'played' in the last 4 minutes (typical song duration)
|
||||
$stmt = $db->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()]);
|
||||
}
|
||||
@ -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') {
|
||||
|
||||
50
index.php
50
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 <span style="color: #facc15;">${requester.toUpperCase()}</span>:`;
|
||||
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 = '<i class="bi bi-youtube"></i> 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';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user