From 4b069537af2711ad319ff56a8335c23c4c630aa4 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 17 Feb 2026 20:12:14 +0000 Subject: [PATCH] Autosave: 20260217-201214 --- api/get_shoutouts.php | 29 +++++ api/send_shoutout.php | 22 ++++ db/migrations/20260217_dj_shoutout.sql | 14 +++ index.php | 168 ++++++++++++++++++++++++- 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 api/get_shoutouts.php create mode 100644 api/send_shoutout.php create mode 100644 db/migrations/20260217_dj_shoutout.sql diff --git a/api/get_shoutouts.php b/api/get_shoutouts.php new file mode 100644 index 0000000..9a79bf5 --- /dev/null +++ b/api/get_shoutouts.php @@ -0,0 +1,29 @@ + false, 'error' => 'User name is required.']); + exit; +} + +try { + // Get the latest unseen shoutout for this user + $stmt = db()->prepare("SELECT id, message, dj_name FROM dj_shoutouts WHERE target_fan_name = ? AND is_seen = 0 ORDER BY created_at DESC LIMIT 1"); + $stmt->execute([$user_name]); + $shoutout = $stmt->fetch(); + + if ($shoutout) { + // Mark as seen immediately so it doesn't pop up again + $update = db()->prepare("UPDATE dj_shoutouts SET is_seen = 1 WHERE id = ?"); + $update->execute([$shoutout['id']]); + + echo json_encode(['success' => true, 'shoutout' => $shoutout]); + } else { + echo json_encode(['success' => true, 'shoutout' => null]); + } +} catch (Exception $e) { + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} diff --git a/api/send_shoutout.php b/api/send_shoutout.php new file mode 100644 index 0000000..49e718e --- /dev/null +++ b/api/send_shoutout.php @@ -0,0 +1,22 @@ + false, 'error' => 'Target and message are required.']); + exit; +} + +try { + $stmt = db()->prepare("INSERT INTO dj_shoutouts (target_fan_name, message, dj_name) VALUES (?, ?, ?)"); + $stmt->execute([$target, $message, $dj_name]); + echo json_encode(['success' => true]); +} catch (Exception $e) { + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} diff --git a/db/migrations/20260217_dj_shoutout.sql b/db/migrations/20260217_dj_shoutout.sql new file mode 100644 index 0000000..166a44f --- /dev/null +++ b/db/migrations/20260217_dj_shoutout.sql @@ -0,0 +1,14 @@ +-- Migration: Create dj_shoutouts table +-- Description: Stores personalized mentions from the DJ to fans. + +CREATE TABLE IF NOT EXISTS dj_shoutouts ( + id INT AUTO_INCREMENT PRIMARY KEY, + target_fan_name VARCHAR(255) NOT NULL, + message TEXT NOT NULL, + dj_name VARCHAR(255) DEFAULT 'Lili', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + is_seen TINYINT(1) DEFAULT 0 +); + +-- Index for faster polling by target name +CREATE INDEX idx_target_unseen ON dj_shoutouts(target_fan_name, is_seen); diff --git a/index.php b/index.php index 2402890..279dea5 100644 --- a/index.php +++ b/index.php @@ -1406,6 +1406,86 @@ $twitter_link = "https://twitter.com/"; box-shadow: 0 4px 12px rgba(236, 72, 153, 0.3); animation: pulse 2s infinite; } + + /* Shoutout Modal Styles */ + .shoutout-modal { + display: none; + position: fixed; + z-index: 5000; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.85); + backdrop-filter: blur(15px); + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.5s ease; + } + .shoutout-modal.show { + display: flex; + opacity: 1; + } + .shoutout-card { + background: linear-gradient(145deg, rgba(30, 30, 30, 0.9), rgba(10, 10, 10, 0.95)); + border: 2px solid var(--primary-color); + padding: 3rem; + border-radius: 40px; + text-align: center; + max-width: 500px; + width: 90%; + position: relative; + transform: scale(0.5) translateY(100px); + transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275); + box-shadow: 0 0 50px rgba(56, 189, 248, 0.6); + } + .shoutout-modal.show .shoutout-card { + transform: scale(1) translateY(0); + } + .shoutout-icon { + font-size: 5rem; + color: #facc15; + margin-bottom: 1.5rem; + filter: drop-shadow(0 0 20px rgba(250, 204, 21, 0.6)); + animation: bounce 2s infinite; + } + .shoutout-title { + font-size: 2.2rem; + font-weight: 900; + background: linear-gradient(to right, #fff, var(--primary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + margin-bottom: 1rem; + text-transform: uppercase; + letter-spacing: 2px; + } + .shoutout-msg { + font-size: 1.2rem; + line-height: 1.6; + color: #fff; + margin-bottom: 2rem; + font-weight: 500; + } + .shoutout-dj { + font-size: 0.8rem; + color: var(--primary-color); + font-weight: 800; + text-transform: uppercase; + letter-spacing: 3px; + } + @keyframes bounce { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-20px); } + } + .shoutout-confetti { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + } @@ -1462,7 +1542,7 @@ $twitter_link = "https://twitter.com/";
-
LILI
+
LILI
ESTÁS ESCUCHANDO:
Cargando stream...
@@ -1904,6 +1984,20 @@ $twitter_link = "https://twitter.com/";
+ +
+
+
+
¡Mención Especial!
+
+
+
— Con cariño, Lili
+ +
+
+ @@ -3385,9 +3479,81 @@ $twitter_link = "https://twitter.com/"; } // Initialize polling + // --- DJ Shoutout Functionality --- + async function adminOpenShoutout() { + const target = prompt("¿A quién quieres mandarle un saludo?"); + if (!target) return; + const message = prompt(`¿Qué mensaje quieres decirle a ${target}?`, "¡Gracias por estar en sintonía con Lili Records!"); + if (!message) return; + + try { + const response = await fetch('api/send_shoutout.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ target_name: target, message: message }) + }); + const data = await response.json(); + if (data.success) { + alert("¡Mención enviada con éxito!"); + } else { + alert("Error: " + data.error); + } + } catch (e) { + console.error("Error sending shoutout:", e); + } + } + + async function pollShoutouts() { + const userName = document.getElementById('user-name').value.trim(); + if (!userName) return; + + try { + const response = await fetch(`api/get_shoutouts.php?user_name=${encodeURIComponent(userName)}`); + const data = await response.json(); + + if (data.success && data.shoutout) { + showShoutoutModal(data.shoutout); + } + } catch (e) { + console.error("Error polling shoutouts:", e); + } + } + + function showShoutoutModal(shoutout) { + const modal = document.getElementById('shoutout-modal'); + const targetEl = document.getElementById('shoutout-target'); + const msgEl = document.getElementById('shoutout-message'); + const djEl = document.getElementById('shoutout-dj-name'); + const userName = document.getElementById('user-name').value.trim(); + + targetEl.innerText = `¡Para ${userName}!`; + msgEl.innerText = shoutout.message; + djEl.innerText = shoutout.dj_name; + + modal.style.display = 'flex'; + setTimeout(() => modal.classList.add('show'), 10); + + // Audio cue if possible + try { + const audio = new Audio('https://www.soundjay.com/buttons/sounds/button-3.mp3'); + audio.volume = 0.5; + audio.play(); + } catch(e) {} + } + + setInterval(pollShoutouts, 5000); setInterval(pollCelebrations, 5000); pollCelebrations(); + // --- End DJ Shoutout Functionality --- + audio.addEventListener('error', function(e) { + console.error('Audio error:', e); + trackTitle.textContent = "Error de conexión. Reintentando..."; + setTimeout(() => { + audio.load(); + if (!audio.paused) audio.play(); + }, 5000); + }); \ No newline at end of file