Auto commit: 2026-02-17T19:34:31.288Z

This commit is contained in:
Flatlogic Bot 2026-02-17 19:34:31 +00:00
parent 9a708e280e
commit e433d2380a
4 changed files with 242 additions and 33 deletions

23
api/get_latest_tips.php Normal file
View File

@ -0,0 +1,23 @@
<?php
require_once __DIR__ . "/../db/config.php";
header("Content-Type: application/json");
try {
$pdo = db();
// Fetch tips from the last 15 seconds to trigger celebrations
$stmt = $pdo->prepare("SELECT * FROM dj_tips WHERE created_at > (NOW() - INTERVAL 15 SECOND) ORDER BY created_at DESC LIMIT 5");
$stmt->execute();
$tips = $stmt->fetchAll();
// Also get current DJ
$stmt = $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'current_dj'");
$dj = $stmt->fetchColumn() ?: "Lili";
echo json_encode([
"success" => true,
"tips" => $tips,
"current_dj" => $dj
]);
} catch (Exception $e) {
echo json_encode(["success" => false, "error" => $e->getMessage()]);
}

51
api/send_tip.php Normal file
View File

@ -0,0 +1,51 @@
<?php
require_once __DIR__ . "/../db/config.php";
header("Content-Type: application/json");
$pdo = db();
$username = $_POST["username"] ?? "";
$amount = intval($_POST["amount"] ?? 100);
if (!$username) {
echo json_encode(["success" => false, "error" => "Inicia sesión para enviar flores"]);
exit;
}
try {
$pdo->beginTransaction();
// Get current DJ
$stmt = $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'current_dj'");
$dj = $stmt->fetchColumn() ?: "Lili";
// Check user points
$stmt = $pdo->prepare("SELECT points FROM fans WHERE name = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if (!$user || $user["points"] < $amount) {
echo json_encode(["success" => false, "error" => "No tienes suficientes puntos ($amount requeridos)"]);
$pdo->rollBack();
exit;
}
// Deduct points
$stmt = $pdo->prepare("UPDATE fans SET points = points - ? WHERE name = ?");
$stmt->execute([$amount, $username]);
// Log tip
$stmt = $pdo->prepare("INSERT INTO dj_tips (sender_name, dj_name, amount) VALUES (?, ?, ?)");
$stmt->execute([$username, $dj, $amount]);
$pdo->commit();
echo json_encode([
"success" => true,
"message" => "¡Has enviado flores a $dj!",
"dj" => $dj
]);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(["success" => false, "error" => $e->getMessage()]);
}

View File

@ -0,0 +1,11 @@
-- Migration: DJ Flores and Current DJ settings
INSERT INTO settings (setting_key, setting_value) VALUES ('current_dj', 'Lili') ON DUPLICATE KEY UPDATE setting_value = setting_value;
CREATE TABLE IF NOT EXISTS dj_tips (
id INT AUTO_INCREMENT PRIMARY KEY,
sender_name VARCHAR(255) NOT NULL,
dj_name VARCHAR(255) NOT NULL,
amount INT NOT NULL,
message VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

190
index.php
View File

@ -1360,39 +1360,53 @@ $twitter_link = "https://twitter.com/";
font-size: 1rem;
color: white;
}
.shop-item-desc {
font-size: 0.75rem;
opacity: 0.6;
}
.shop-item-price {
font-weight: 800;
color: #facc15;
display: flex;
align-items: center;
gap: 4px;
}
.pinned-message-container {
background: linear-gradient(90deg, rgba(56, 189, 248, 0.2), rgba(0, 200, 83, 0.2));
border: 1px solid var(--primary-color);
border-radius: 12px;
padding: 0.8rem;
margin-bottom: 1rem;
display: none;
animation: fadeIn 0.5s ease;
position: relative;
}
.pinned-label {
font-size: 0.6rem;
font-weight: 800;
color: var(--primary-color);
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 4px;
display: flex;
align-items: center;
gap: 4px;
}
</style>
.shop-item-desc {
font-size: 0.75rem;
opacity: 0.7;
}
/* Celebration & Flowers */
#celebration-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
overflow: hidden;
}
.flower-particle {
position: absolute;
font-size: 2rem;
user-select: none;
animation: fall-and-sway var(--duration) linear forwards;
opacity: 0;
}
@keyframes fall-and-sway {
0% { transform: translateY(-10vh) translateX(0) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(110vh) translateX(var(--sway)) rotate(360deg); opacity: 0; }
}
.dj-badge {
background: linear-gradient(135deg, #f472b6, #db2777);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.7rem;
font-weight: 800;
display: inline-flex;
align-items: center;
gap: 5px;
margin-bottom: 8px;
box-shadow: 0 4px 12px rgba(236, 72, 153, 0.3);
animation: pulse 2s infinite;
}
</style>
</head>
<body>
<div class="background"></div>
@ -1447,6 +1461,9 @@ $twitter_link = "https://twitter.com/";
<img id="track-cover" src="./assets/pasted-20260215-163754-def41f49.png" alt="Cover" crossorigin="anonymous" onerror="this.style.display='none'; document.getElementById('cover-placeholder').style.display='block';">
</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>
<span class="track-label">ESTÁS ESCUCHANDO:</span>
<div id="track-title" class="track-title" onclick="copyTrackTitle()" title="Toca para copiar">Cargando stream...</div>
<div id="track-artist" class="track-artist" style="font-size: 0.95rem; font-weight: 600; opacity: 0.8; color: var(--primary-color); text-transform: uppercase; letter-spacing: 1px; margin-top: 2px;">Lili Records Radio</div>
@ -1480,6 +1497,10 @@ $twitter_link = "https://twitter.com/";
<i class="bi bi-heart"></i>
<span id="like-count" style="font-size: 0.9rem; color: white; opacity: 0.8; font-weight: bold;"></span>
</button>
<button id="send-flowers-btn" onclick="sendFlowersToDJ()" style="background: none; border: none; color: #f472b6; font-size: 1.8rem; cursor: pointer; transition: transform 0.2s; display: flex; flex-direction: column; align-items: center; justify-content: center; margin-left: 10px;" title="Regalar flores al DJ">
<i class="bi bi-flower1"></i>
<span style="font-size: 0.6rem; color: white; opacity: 0.8; font-weight: bold; margin-top: -5px;">FLORES</span>
</button>
</div>
<div class="controls">
@ -1880,6 +1901,9 @@ $twitter_link = "https://twitter.com/";
</div>
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script>
<!-- Celebration Overlay -->
<div id="celebration-overlay"></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>
@ -3264,6 +3288,106 @@ $twitter_link = "https://twitter.com/";
setInterval(fetchActivePerks, 10000);
fetchActivePerks();
// --- End Radio Shop Functionality ---
// --- DJ Flores Functionality ---
let lastCelebrationId = 0;
const shownTips = new Set();
async function sendFlowersToDJ() {
const userName = document.getElementById('user-name').value.trim();
if (!userName) {
alert('Por favor, ingresa tu nombre arriba para regalar flores.');
document.getElementById('user-name').focus();
return;
}
if (!confirm(`¿Quieres enviarle un ramo de flores al DJ por 100 puntos?`)) return;
try {
const formData = new FormData();
formData.append('username', userName);
formData.append('amount', 100);
const response = await fetch('api/send_tip.php', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
alert(data.message);
launchFlowerCelebration(); // Local trigger
fetchLeaderboard(); // Update points
} else {
alert(data.error);
}
} catch (e) {
console.error('Error sending flowers:', e);
}
}
async function pollCelebrations() {
try {
const response = await fetch('api/get_latest_tips.php');
const data = await response.json();
if (data.success) {
// Update DJ Name
if (data.current_dj) {
document.getElementById('current-dj-name').innerText = data.current_dj.toUpperCase();
}
// Check for new tips
data.tips.forEach(tip => {
if (!shownTips.has(tip.id)) {
shownTips.add(tip.id);
launchFlowerCelebration();
console.log(`Celebration for tip from ${tip.sender_name}`);
}
});
// Cleanup set to keep it small
if (shownTips.size > 50) {
const it = shownTips.values();
shownTips.delete(it.next().value);
}
}
} catch (e) {
console.error('Error polling celebrations:', e);
}
}
function launchFlowerCelebration() {
const container = document.getElementById('celebration-overlay');
const emojis = ['🌸', '🌹', '🌺', '🌻', '🌼', '🌷', '✨', '💖'];
const count = 30;
for (let i = 0; i < count; i++) {
setTimeout(() => {
const flower = document.createElement('div');
flower.className = 'flower-particle';
flower.innerText = emojis[Math.floor(Math.random() * emojis.length)];
const left = Math.random() * 100;
const sway = (Math.random() - 0.5) * 200;
const duration = 3 + Math.random() * 4;
flower.style.left = `${left}%`;
flower.style.setProperty('--sway', `${sway}px`);
flower.style.setProperty('--duration', `${duration}s`);
flower.style.fontSize = `${1.5 + Math.random() * 2}rem`;
container.appendChild(flower);
setTimeout(() => flower.remove(), duration * 1000);
}, i * 100);
}
}
// Initialize polling
setInterval(pollCelebrations, 5000);
pollCelebrations();
</script>
</body>
</html>