Autosave: 20260217-201214
This commit is contained in:
parent
e433d2380a
commit
4b069537af
29
api/get_shoutouts.php
Normal file
29
api/get_shoutouts.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
$user_name = $_GET['user_name'] ?? '';
|
||||
|
||||
if (empty($user_name)) {
|
||||
echo json_encode(['success' => 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()]);
|
||||
}
|
||||
22
api/send_shoutout.php
Normal file
22
api/send_shoutout.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$target = $data['target_name'] ?? '';
|
||||
$message = $data['message'] ?? '';
|
||||
$dj_name = $data['dj_name'] ?? 'Lili';
|
||||
|
||||
if (empty($target) || empty($message)) {
|
||||
echo json_encode(['success' => 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()]);
|
||||
}
|
||||
14
db/migrations/20260217_dj_shoutout.sql
Normal file
14
db/migrations/20260217_dj_shoutout.sql
Normal file
@ -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);
|
||||
168
index.php
168
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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -1462,7 +1542,7 @@ $twitter_link = "https://twitter.com/";
|
||||
</div>
|
||||
<div class="track-info">
|
||||
<div id="dj-host-container" style="display: flex; align-items: center; gap: 8px;">
|
||||
<div class="dj-badge"><i class="bi bi-mic-fill"></i> <span id="current-dj-name">LILI</span></div>
|
||||
<div class="dj-badge" onclick="adminOpenShoutout()" style="cursor: pointer;" title="DJ Panel (Admin)"><i class="bi bi-mic-fill"></i> <span id="current-dj-name">LILI</span></div>
|
||||
</div>
|
||||
<span class="track-label">ESTÁS ESCUCHANDO:</span>
|
||||
<div id="track-title" class="track-title" onclick="copyTrackTitle()" title="Toca para copiar">Cargando stream...</div>
|
||||
@ -1904,6 +1984,20 @@ $twitter_link = "https://twitter.com/";
|
||||
<!-- Celebration Overlay -->
|
||||
<div id="celebration-overlay"></div>
|
||||
|
||||
<!-- Shoutout Modal -->
|
||||
<div id="shoutout-modal" class="shoutout-modal" onclick="this.classList.remove('show'); setTimeout(() => this.style.display = 'none', 500)">
|
||||
<div class="shoutout-card" onclick="event.stopPropagation()">
|
||||
<div class="shoutout-icon"><i class="bi bi-megaphone-fill"></i></div>
|
||||
<div class="shoutout-title">¡Mención Especial!</div>
|
||||
<div id="shoutout-target" style="font-size: 1.5rem; color: #facc15; font-weight: 800; margin-bottom: 1rem;"></div>
|
||||
<div id="shoutout-message" class="shoutout-msg"></div>
|
||||
<div class="shoutout-dj">— Con cariño, <span id="shoutout-dj-name">Lili</span> —</div>
|
||||
<button onclick="document.getElementById('shoutout-modal').classList.remove('show'); setTimeout(() => document.getElementById('shoutout-modal').style.display = 'none', 500)" style="margin-top: 2rem; background: var(--primary-color); border: none; color: black; padding: 10px 30px; border-radius: 20px; font-weight: 800; cursor: pointer; transition: all 0.3s;">
|
||||
¡GRACIAS!
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<audio id="radio-audio" src="https://listen.radioking.com/radio/828046/stream/897251" preload="auto" crossorigin="anonymous"></audio>
|
||||
<audio id="welcome-sound" src="https://assets.mixkit.co/active_storage/sfx/2013/2013-preview.mp3" preload="auto"></audio>
|
||||
|
||||
@ -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);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user