38018-vm/index.php
2026-01-31 02:56:49 +00:00

745 lines
24 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
require_once __DIR__ . '/db/config.php';
@ini_set('display_errors', '0');
@error_reporting(E_ALL);
session_start();
// Simple admin check: access via index.php?admin=lili
if (isset($_GET['admin']) && $_GET['admin'] === 'lili') {
$_SESSION['is_admin'] = true;
}
if (isset($_GET['logout'])) {
unset($_SESSION['is_admin']);
}
$isAdmin = !empty($_SESSION['is_admin']);
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Lili Records Radio - La mejor música en vivo.';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
$streamUrl = "https://play.radioking.io/lili-record-s-radio";
$whatsappNumber = "5359177041";
$whatsappLink = "https://wa.me/" . $whatsappNumber;
$youtubeUrl = "https://www.youtube.com/@lilirecords";
$promoImage = "assets/pasted-20260130-234122-115a4b49.png";
$qrImage = "assets/pasted-20260131-000858-4fff58f0.jpg";
$logoImage = "assets/pasted-20260131-002028-7985dfae.png";
// Fetch latest requests
$requests = [];
try {
$stmt = db()->query("SELECT name, phone, message, created_at FROM listener_requests ORDER BY created_at DESC LIMIT 20");
$requests = $stmt->fetchAll();
} catch (Exception $e) {
// Silently fail if table doesn't exist yet or other DB error
}
?>
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Lili Records Radio</title>
<?php if ($projectDescription): ?>
<meta name="description" content="<?= htmlspecialchars($projectDescription) ?>" />
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
:root {
--primary-color: #ff2d55;
--glass-bg: rgba(0, 0, 0, 0.6);
--glass-border: rgba(255, 255, 255, 0.15);
}
body {
font-family: 'Inter', sans-serif;
background: #050505;
color: #fff;
min-height: 100vh;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow-x: hidden;
}
/* Background Image */
.bg-image {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('<?= $promoImage ?>') center/cover no-repeat;
filter: brightness(0.3) blur(5px);
z-index: -1;
}
.main-wrapper {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
width: 100%;
max-width: 1600px;
padding: 2rem;
gap: 2rem;
z-index: 1;
}
@media (max-width: 1300px) {
.main-wrapper {
flex-direction: column;
align-items: center;
padding: 1rem;
gap: 1.5rem;
}
.left-column, .admin-column {
position: static;
flex: none;
width: 100%;
max-width: 500px;
}
body {
overflow-y: auto;
height: auto;
}
}
.left-column {
position: sticky;
top: 2rem;
flex: 0 0 300px;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.admin-column {
position: sticky;
top: 2rem;
flex: 0 0 300px;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.player-container {
background: var(--glass-bg);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid var(--glass-border);
border-radius: 28px;
padding: 1.5rem;
width: 100%;
text-align: center;
box-shadow: 0 20px 40px rgba(0,0,0,0.6);
transition: all 0.3s ease;
position: relative;
}
.right-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 2rem;
max-width: 700px;
width: 100%;
min-width: 0;
}
.promo-image {
width: 100%;
height: auto;
border-radius: 30px;
box-shadow: 0 30px 60px rgba(0,0,0,0.7);
border: 1px solid var(--glass-border);
transition: transform 0.5s ease;
}
.comments-window {
background: var(--glass-bg);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 30px;
padding: 1.8rem;
box-shadow: 0 30px 60px rgba(0,0,0,0.5);
display: flex;
flex-direction: column;
min-height: 400px;
}
.comments-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.2rem;
padding-bottom: 0.8rem;
border-bottom: 1px solid var(--glass-border);
}
.comments-list {
overflow-y: auto;
flex: 1;
padding-right: 0.8rem;
max-height: 500px;
}
.comments-list::-webkit-scrollbar {
width: 4px;
}
.comments-list::-webkit-scrollbar-thumb {
background: var(--glass-border);
border-radius: 10px;
}
.comment-item {
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.05);
border-radius: 16px;
padding: 1.2rem;
margin-bottom: 1.2rem;
font-size: 0.95rem;
position: relative;
transition: all 0.3s ease;
}
.comment-item:hover {
background: rgba(255,255,255,0.08);
transform: translateX(5px);
}
.comment-user {
font-weight: 700;
color: var(--primary-color);
margin-bottom: 0.3rem;
display: block;
font-size: 1rem;
}
.comment-text {
opacity: 0.9;
line-height: 1.5;
}
.comment-date {
font-size: 0.75rem;
opacity: 0.4;
display: block;
margin-top: 0.6rem;
}
.comment-actions {
position: absolute;
top: 15px;
right: 15px;
}
.btn-wa-reply {
background: #25d366;
color: #fff;
border: none;
border-radius: 50%;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
transition: all 0.3s ease;
text-decoration: none;
box-shadow: 0 4px 10px rgba(37, 211, 102, 0.3);
}
.btn-wa-reply:hover {
transform: scale(1.15) rotate(10deg);
color: #fff;
box-shadow: 0 6px 15px rgba(37, 211, 102, 0.5);
}
.request-form {
margin-top: 1.5rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.form-control-glass {
background: #ffffff;
border: 1px solid rgba(255,255,255,0.1);
color: #000;
border-radius: 16px;
padding: 0.8rem 1.2rem;
font-weight: 500;
}
.form-control-glass::placeholder {
color: #777;
}
.btn-send-request {
background: linear-gradient(45deg, var(--primary-color), #ff512f);
border: none;
border-radius: 16px;
padding: 0.8rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
box-shadow: 0 10px 20px rgba(255, 45, 85, 0.3);
}
.btn-send-request:hover {
transform: translateY(-3px);
box-shadow: 0 15px 25px rgba(255, 45, 85, 0.5);
}
.radio-logo {
width: 70px;
height: 70px;
border-radius: 50%;
background: linear-gradient(135deg, #ff2d55, #ff512f);
margin: 0 auto 1rem;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 25px rgba(255, 45, 85, 0.5);
animation: pulse 2.5s infinite;
overflow: hidden;
border: 3px solid rgba(255,255,255,0.2);
}
.radio-logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
@keyframes pulse {
0% { transform: scale(1); box-shadow: 0 0 20px rgba(255, 45, 85, 0.4); }
50% { transform: scale(1.08); box-shadow: 0 0 40px rgba(255, 45, 85, 0.7); }
100% { transform: scale(1); box-shadow: 0 0 20px rgba(255, 45, 85, 0.4); }
}
.song-title {
font-size: 1.1rem;
font-weight: 800;
margin-bottom: 0.2rem;
display: block;
color: #fff;
}
.artist-name {
font-size: 0.9rem;
opacity: 0.6;
font-weight: 500;
}
.btn-play {
width: 50px;
height: 50px;
border-radius: 50%;
background: #fff;
color: #000;
border: none;
font-size: 1.2rem;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
cursor: pointer;
}
.btn-play:hover {
transform: scale(1.1);
background: var(--primary-color);
color: #fff;
}
.volume-slider {
width: 100%;
height: 6px;
-webkit-appearance: none;
background: rgba(255,255,255,0.1);
border-radius: 10px;
outline: none;
}
.volume-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 14px;
height: 14px;
background: #fff;
border-radius: 50%;
cursor: pointer;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
.qr-mini-box {
background: rgba(255,255,255,0.08);
padding: 8px;
border-radius: 16px;
border: 1px solid var(--glass-border);
width: 85px;
transition: all 0.3s ease;
}
.qr-mini-box:hover {
background: rgba(255,255,255,0.15);
border-color: var(--primary-color);
transform: scale(1.05);
}
.qr-text-mini {
font-size: 0.65rem;
margin-top: 5px;
font-weight: 800;
letter-spacing: 0.5px;
}
.admin-stats-box {
background: var(--glass-bg);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid var(--glass-border);
border-radius: 28px;
padding: 1.5rem;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.6);
animation: fadeIn 0.8s ease;
text-align: center;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.whatsapp-btn {
position: fixed;
bottom: 30px;
left: 30px;
width: 65px;
height: 65px;
background: #25d366;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.2rem;
box-shadow: 0 15px 35px rgba(37, 211, 102, 0.4);
text-decoration: none;
z-index: 100;
animation: bounce 2.5s infinite;
}
.btn-youtube-float {
position: fixed;
bottom: 110px;
left: 30px;
width: 65px;
height: 65px;
background: #ff0000;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
box-shadow: 0 15px 35px rgba(255, 0, 0, 0.4);
text-decoration: none;
z-index: 100;
animation: bounce 2.8s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
40% {transform: translateY(-12px);}
60% {transform: translateY(-6px);}
}
.live-badge {
position: absolute;
top: 15px;
left: 15px;
background: var(--primary-color);
padding: 4px 10px;
border-radius: 20px;
font-size: 0.65rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 1.5px;
box-shadow: 0 4px 10px rgba(255, 45, 85, 0.4);
}
.policy-link {
color: #fff;
opacity: 0.5;
font-size: 0.8rem;
text-decoration: none;
border-bottom: 1px dashed rgba(255,255,255,0.3);
padding-bottom: 2px;
transition: all 0.3s ease;
}
.policy-link:hover {
opacity: 1;
color: var(--primary-color);
border-bottom-color: var(--primary-color);
}
</style>
</head>
<body>
<div class="bg-image"></div>
<div class="main-wrapper">
<!-- Left: Player -->
<div class="left-column">
<aside class="player-container">
<div class="live-badge">En Vivo</div>
<div class="radio-logo">
<img src="<?= $logoImage ?>" alt="Lili Records Logo">
</div>
<div class="song-info mb-3">
<span class="song-title" id="songTitle">Conectando...</span>
<span class="artist-name" id="artistName">Lili Records Radio</span>
</div>
<div class="player-controls-row d-flex align-items-center gap-3">
<button class="btn-play" id="playBtn">
<i class="fas fa-play" id="playIcon"></i>
</button>
<div class="flex-grow-1 d-flex align-items-center gap-2">
<i class="fas fa-volume-off opacity-50" style="font-size: 0.8rem;"></i>
<input type="range" class="volume-slider" id="volumeSlider" min="0" max="1" step="0.01" value="0.8">
<i class="fas fa-volume-up opacity-50" style="font-size: 0.8rem;"></i>
</div>
</div>
<?php if ($isAdmin): ?>
<div class="mt-4 pt-3 border-top border-white border-opacity-10">
<div class="mb-2 small text-primary"><i class="fas fa-shield-alt me-1"></i> MODO ADMIN</div>
<a href="?logout=1" class="btn btn-sm btn-outline-danger px-3 rounded-pill" style="font-size: 0.75rem;">Cerrar Administración</a>
</div>
<?php endif; ?>
</aside>
</div>
<!-- Center: Image + Comments -->
<div class="right-content">
<img src="<?= $promoImage ?>" alt="Lili Records Promo" class="promo-image">
<div class="comments-window">
<?php if ($isAdmin): ?>
<div class="comments-header">
<div>
<h5 class="mb-1"><i class="fas fa-user-shield me-2 text-primary"></i>Panel de Control</h5>
<p class="small opacity-50 mb-0">Gestiona los mensajes de tus oyentes</p>
</div>
<div class="qr-mini-box text-center">
<img src="<?= $qrImage ?>" alt="QR Pago" class="w-100 rounded-2">
<p class="qr-text-mini text-white mb-0">APOYAR</p>
</div>
</div>
<div class="comments-list" id="commentsList">
<?php if (empty($requests)): ?>
<div class="text-center py-5 opacity-40">
<i class="fas fa-comment-slash fa-3x mb-3"></i>
<p>Aún no hay mensajes recibidos.</p>
</div>
<?php else: ?>
<?php foreach ($requests as $req): ?>
<div class="comment-item">
<span class="comment-user"><?= htmlspecialchars($req['name']) ?></span>
<p class="comment-text mb-0"><?= htmlspecialchars($req['message']) ?></p>
<span class="comment-date"><?= date('d M Y, H:i', strtotime($req['created_at'])) ?></span>
<?php if (!empty($req['phone'])): ?>
<div class="comment-actions">
<a href="https://wa.me/<?= preg_replace('/[^0-9]/', '', $req['phone']) ?>" class="btn-wa-reply" target="_blank">
<i class="fab fa-whatsapp"></i>
</a>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<?php else: ?>
<div class="comments-header border-0 mb-3">
<div>
<h5 class="mb-1"><i class="fas fa-microphone-alt me-2 text-primary"></i>¡Envíanos tu mensaje!</h5>
<p class="small opacity-60 mb-0">Pide tu canción favorita o envía un saludo.</p>
</div>
<div class="qr-mini-box text-center">
<img src="<?= $qrImage ?>" alt="QR Pago" class="w-100 rounded-2">
<p class="qr-text-mini text-white mb-0">APOYAR</p>
</div>
</div>
<div class="comments-list" style="max-height: 250px;">
<?php foreach (array_slice($requests, 0, 5) as $req): ?>
<div class="comment-item py-2 px-3 mb-2 border-0 bg-white bg-opacity-5">
<span class="comment-user" style="font-size: 0.85rem;"><?= htmlspecialchars($req['name']) ?></span>
<p class="comment-text mb-0" style="font-size: 0.9rem;"><?= htmlspecialchars($req['message']) ?></p>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<form action="submit_request.php" method="POST" class="request-form mt-auto">
<div class="row g-2">
<div class="col-sm-6">
<input type="text" name="name" class="form-control form-control-glass" placeholder="Nombre completo" required>
</div>
<div class="col-sm-6">
<input type="text" name="phone" class="form-control form-control-glass" placeholder="WhatsApp / Teléfono">
</div>
</div>
<div class="input-group">
<textarea name="message" class="form-control form-control-glass" rows="1" placeholder="Escribe aquí tu petición o saludo..." required></textarea>
<button type="submit" class="btn btn-send-request text-white px-4">
<i class="fas fa-paper-plane"></i>
</button>
</div>
<div class="text-center mt-2">
<span class="policy-link" data-bs-toggle="modal" data-bs-target="#policyModal">Ver Políticas de Privacidad</span>
</div>
</form>
</div>
<div class="mt-4 text-center pb-4">
<p class="small text-white opacity-40 mb-0">&copy; 2026 Lili Record´s Radio. All rights reserved.</p>
</div>
</div>
<!-- Right: Admin Stats -->
<?php if ($isAdmin): ?>
<div class="admin-column">
<div class="admin-stats-box">
<h6 class="small mb-3 d-flex align-items-center justify-content-center font-weight-bold">
<i class="fas fa-globe-americas me-2 text-primary"></i>
MAPA DE VISITANTES
</h6>
<div class="d-flex justify-content-center mb-4 py-2" style="background: rgba(255,255,255,0.03); border-radius: 20px; min-height: 160px;">
<!-- Widget Map Whos.amung.us -->
<script id="_waumap">var _wau = _wau || []; _wau.push(["map", "lili-records", "map", "260", "130", "cool", "star-red"]);</script>
<script src="https://whos.amung.us/map.js"></script>
</div>
<h6 class="small mb-3 d-flex align-items-center justify-content-center font-weight-bold">
<i class="fas fa-users me-2 text-primary"></i>
OYENTES ONLINE
</h6>
<div class="d-flex justify-content-center py-3" style="background: rgba(255,255,255,0.03); border-radius: 20px;">
<script id="_wauq0z">var _wau = _wau || []; _wau.push(["classic", "lili-records", "q0z"]);</script>
<script src="https://whos.amung.us/classic.js"></script>
</div>
<div class="mt-4 pt-3 border-top border-white border-opacity-10 text-center">
<p class="small opacity-50 mb-0">
Estadísticas activas
</p>
<a href="https://whos.amung.us/stats/lili-records/" target="_blank" class="btn btn-link text-primary p-0 mt-1" style="font-size: 0.7rem; text-decoration: none;">Ver panel completo <i class="fas fa-external-link-alt ms-1"></i></a>
</div>
</div>
</div>
<?php endif; ?>
</div>
<!-- Modal Política de Privacidad -->
<div class="modal fade" id="policyModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content border-0" style="background: rgba(20,20,20,0.95); border-radius: 30px; backdrop-filter: blur(20px);">
<div class="modal-header border-white border-opacity-10 px-4 py-3">
<h5 class="modal-title font-weight-bold">POLÍTICA DE PRIVACIDAD Y CONTENIDO</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-4" style="font-size: 0.95rem; line-height: 1.7; opacity: 0.9;">
<ul class="list-unstyled">
<li class="mb-3 d-flex gap-3"><i class="fas fa-check-circle text-primary mt-1"></i> No se permiten comentarios indecentes, ofensivos o discriminatorios.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check-circle text-primary mt-1"></i> No aceptamos contenidos políticos; nuestro enfoque es puramente cultural y musical.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check-circle text-primary mt-1"></i> No recopilamos datos personales sensibles sin autorización previa y explícita.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check-circle text-primary mt-1"></i> No compartimos información con terceros sin consentimiento del propietario.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check-circle text-primary mt-1"></i> Los contenidos enviados son promovidos exclusivamente bajo petición y permiso del usuario.</li>
<li class="mb-3 d-flex gap-3"><i class="fas fa-check-circle text-primary mt-1"></i> Respetamos la privacidad del dispositivo y no utilizamos rastreadores invasivos de terceros.</li>
</ul>
</div>
<div class="modal-footer border-0 px-4 pb-4">
<button type="button" class="btn btn-primary px-5 rounded-pill" data-bs-dismiss="modal">Entendido</button>
</div>
</div>
</div>
</div>
<a href="<?= $youtubeUrl ?>" target="_blank" class="btn-youtube-float" title="YouTube">
<i class="fab fa-youtube"></i>
</a>
<a href="track_click.php?type=whatsapp_open&redirect=<?= urlencode($whatsappLink) ?>" class="whatsapp-btn" title="WhatsApp">
<i class="fab fa-whatsapp"></i>
</a>
<audio id="audioPlayer" src="<?= $streamUrl ?>" crossorigin="anonymous"></audio>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const audio = document.getElementById('audioPlayer');
const playBtn = document.getElementById('playBtn');
const playIcon = document.getElementById('playIcon');
const volumeSlider = document.getElementById('volumeSlider');
const songTitle = document.getElementById('songTitle');
const artistName = document.getElementById('artistName');
let isPlaying = false;
playBtn.addEventListener('click', () => {
if (isPlaying) {
audio.pause();
playIcon.classList.replace('fa-pause', 'fa-play');
} else {
audio.play().catch(e => console.error("Error playing audio:", e));
playIcon.classList.replace('fa-play', 'fa-pause');
}
isPlaying = !isPlaying;
});
volumeSlider.addEventListener('input', (e) => {
audio.volume = e.target.value;
});
async function fetchMetadata() {
try {
const response = await fetch('https://api.radioking.io/widget/radio/lili-record-s-radio/track/current');
const data = await response.json();
if (data && data.title) {
songTitle.textContent = data.title;
artistName.textContent = data.artist || 'Lili Records Radio';
}
} catch (error) {
console.error('Error fetching metadata:', error);
}
}
setInterval(fetchMetadata, 10000);
fetchMetadata();
</script>
</body>
</html>