Auto commit: 2026-02-25T21:49:22.586Z

This commit is contained in:
Flatlogic Bot 2026-02-25 21:49:22 +00:00
parent 66f33d8ab6
commit d28bf682c9
2 changed files with 79 additions and 87 deletions

View File

@ -48,49 +48,65 @@ try {
}
if (!$shouldWait) {
// 3. 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) {
// Find YouTube info before playing if missing
$youtubeUrl = $next['youtube_url'];
$duration = $next['duration'] ?? 240;
// 3. Take the oldest pending request and "execute" it using a transaction to avoid race conditions
$db->beginTransaction();
try {
$stmt = $db->query("SELECT * FROM song_requests WHERE status = 'pending' ORDER BY is_priority DESC, created_at ASC LIMIT 1 FOR UPDATE");
$next = $stmt->fetch();
if (!$youtubeUrl) {
try {
require_once __DIR__ . '/../ai/LocalAIApi.php';
$artist = $next['artist'];
$song = $next['song'];
$aiResp = LocalAIApi::createResponse([
'input' => [
['role' => 'system', 'content' => 'Eres un asistente de radio. Tu tarea es encontrar el ID de YouTube oficial y la duración aproximada en segundos para una canción. Responde ÚNICAMENTE con un JSON: {"id": "...", "duration": ...}. Si no estás seguro, usa id null y duration 240.'],
['role' => 'user', 'content' => "Encuentra el ID de YouTube y duración para: $artist - $song"]
]
]);
if (!empty($aiResp['success'])) {
$jsonText = LocalAIApi::extractText($aiResp);
$data = json_decode($jsonText, true);
if ($data && isset($data['id']) && $data['id'] !== null) {
$youtubeUrl = "https://www.youtube.com/watch?v={$data['id']}";
$duration = (int)($data['duration'] ?? 240);
}
}
} catch (Exception $e) {}
}
if ($next) {
// Mark as played immediately within the transaction
$stmt = $db->prepare("UPDATE song_requests SET status = 'played', created_at = NOW() WHERE id = ?");
$stmt->execute([$next['id']]);
$db->commit();
$stmt = $db->prepare("UPDATE song_requests SET status = 'played', youtube_url = ?, duration = ?, created_at = NOW() WHERE id = ?");
$stmt->execute([$youtubeUrl, $duration, $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;
// Now that we "own" this request, we can do the slow AI/log operations
$youtubeUrl = $next['youtube_url'];
$duration = $next['duration'] ?? 240;
if (!$youtubeUrl) {
try {
require_once __DIR__ . '/../ai/LocalAIApi.php';
$artist = $next['artist'];
$song = $next['song'];
$aiResp = LocalAIApi::createResponse([
'input' => [
['role' => 'system', 'content' => 'Eres un asistente de radio. Tu tarea es encontrar el ID de YouTube oficial y la duración aproximada en segundos para una canción. Responde ÚNICAMENTE con un JSON: {"id": "...", "duration": ...}. Si no estás seguro, usa id null y duration 240.'],
['role' => 'user', 'content' => "Encuentra el ID de YouTube y duración para: $artist - $song"]
]
]);
if (!empty($aiResp['success'])) {
$jsonText = LocalAIApi::extractText($aiResp);
$data = json_decode($jsonText, true);
if ($data && isset($data['id']) && $data['id'] !== null) {
$youtubeUrl = "https://www.youtube.com/watch?v={$data['id']}";
$duration = (int)($data['duration'] ?? 240);
}
}
} catch (Exception $e) {}
// Update with AI info
if ($youtubeUrl) {
$stmt = $db->prepare("UPDATE song_requests SET youtube_url = ?, duration = ? WHERE id = ?");
$stmt->execute([$youtubeUrl, $duration, $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;
} else {
$db->rollBack();
}
} catch (Exception $e) {
$db->rollBack();
throw $e;
}
}

View File

@ -70,58 +70,34 @@ if ($method === 'POST') {
}
try {
// 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;
// Check for duplicates
// 1. Check if it's already in the pending queue
$stmt = $db->prepare("SELECT id FROM song_requests WHERE artist = ? AND song = ? AND status = 'pending' LIMIT 1");
$stmt->execute([$artist, $song]);
if ($stmt->fetch()) {
echo json_encode(['success' => false, 'error' => 'Esta canción ya está en la cola de espera.']);
exit;
}
// 2. Check if it was played in the last 30 minutes (to avoid repetition)
// We skip this check for priority requests or if the DJ is adding it
if ($source !== 'admin') {
$stmt = $db->prepare("SELECT id FROM song_requests WHERE artist = ? AND song = ? AND status = 'played' AND created_at > DATE_SUB(NOW(), INTERVAL 30 MINUTE) LIMIT 1");
$stmt->execute([$artist, $song]);
if ($stmt->fetch()) {
echo json_encode(['success' => false, 'error' => 'Esta canción se ha reproducido recientemente. ¡Prueba con otra!']);
exit;
}
}
// All requests start as pending. The automation.php script (called by clients)
// will handle moving them to 'played' status atomically.
$initialStatus = 'pending';
$stmt = $db->prepare("INSERT INTO song_requests (artist, song, requester, source, status, duration) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$artist, $song, $requester, $source, $initialStatus, 240]);
$requestId = $db->lastInsertId();
if ($wasAutoExecuted) {
// Try to find a YouTube link and duration for the song using AI
$youtubeUrl = null;
$duration = 240;
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 y la duración aproximada en segundos para una canción. Responde ÚNICAMENTE con un JSON: {"id": "...", "duration": ...}. Si no estás seguro, usa id null y duration 240.'],
['role' => 'user', 'content' => "Encuentra el ID de YouTube y duración para: $artist - $song"]
]
]);
if (!empty($aiResp['success'])) {
$jsonText = LocalAIApi::extractText($aiResp);
$data = json_decode($jsonText, true);
if ($data && isset($data['id']) && $data['id'] !== null) {
$youtubeUrl = "https://www.youtube.com/watch?v={$data['id']}";
$duration = (int)($data['duration'] ?? 240);
}
}
} catch (Exception $e) {
error_log("AI YouTube search failed: " . $e->getMessage());
}
if ($youtubeUrl || $duration != 240) {
$stmt = $db->prepare("UPDATE song_requests SET youtube_url = ?, duration = ? WHERE id = ?");
$stmt->execute([$youtubeUrl, $duration, $requestId]);
}
// 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]);
}
// Award points for song request
if ($requester !== 'Anónimo') {
require_once __DIR__ . '/../includes/points_helper.php';