T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/public_html/radio/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/public_html/radio/live.php
<?php
/**
 * Public Live Radio Player
 * Consumer-facing live radio streaming interface
 */

session_start();
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/includes/functions.php';

$pdo = getDBConnection();

if (!$pdo) {
    die("Database connection failed. Please check your configuration.");
}

// Check if radio_streams table exists, if not, show helpful message
try {
    $pdo->query("SELECT 1 FROM radio_streams LIMIT 1");
} catch (PDOException $e) {
    // Table doesn't exist, show setup message
    die("
    <html>
    <head><title>Setup Required</title></head>
    <body style='font-family: Arial; padding: 2rem;'>
        <h1>Database Setup Required</h1>
        <p>The live streaming tables need to be created. Please run:</p>
        <pre style='background: #f5f5f5; padding: 1rem; border-radius: 4px;'>
php /radio/migrations/add_live_streaming_tables.php
        </pre>
        <p>Or visit: <a href='/radio/migrations/add_live_streaming_tables.php'>/radio/migrations/add_live_streaming_tables.php</a></p>
    </body>
    </html>
    ");
}

// Get station ID from query parameter or default to first active station
$station_id = isset($_GET['station']) ? (int)$_GET['station'] : null;

if (!$station_id) {
    // Get first active station with a live stream
    try {
        $stmt = $pdo->prepare("
            SELECT rs.id, rs.station_name, rs.call_sign, rs.logo_url, rs.description,
                   rstr.id as stream_id, rstr.stream_url, rstr.is_live, rstr.listener_count
            FROM radio_stations rs
            LEFT JOIN radio_streams rstr ON rs.id = rstr.station_id
            WHERE rs.subscription_status = 'active' 
            AND rs.is_active = 1
            AND rstr.is_live = 1
            ORDER BY rstr.listener_count DESC, rs.id ASC
            LIMIT 1
        ");
        $stmt->execute();
        $station = $stmt->fetch();
    } catch (PDOException $e) {
        error_log("Error fetching station: " . $e->getMessage());
        $station = null;
    }
    
    if ($station) {
        $station_id = $station['id'];
        $stream_id = $station['stream_id'];
    } else {
        // No live stream, show placeholder
        $station = null;
        $stream_id = null;
    }
} else {
    // Get specific station
    try {
        $stmt = $pdo->prepare("
            SELECT rs.id, rs.station_name, rs.call_sign, rs.logo_url, rs.description,
                   rstr.id as stream_id, rstr.stream_url, rstr.is_live, rstr.listener_count
            FROM radio_stations rs
            LEFT JOIN radio_streams rstr ON rs.id = rstr.station_id
            WHERE rs.id = ? AND rs.subscription_status = 'active' AND rs.is_active = 1
        ");
        $stmt->execute([$station_id]);
        $station = $stmt->fetch();
        $stream_id = $station['stream_id'] ?? null;
    } catch (PDOException $e) {
        error_log("Error fetching station: " . $e->getMessage());
        $station = null;
        $stream_id = null;
    }
}

// Get current track playing
$now_playing = null;
if ($stream_id) {
    try {
        $stmt = $pdo->prepare("
            SELECT np.*, mt.title, mt.audio_url, mt.image_url, mt.duration,
                   u.name as artist_name, u.id as artist_id
            FROM radio_now_playing np
            JOIN music_tracks mt ON np.track_id = mt.id
            LEFT JOIN users u ON mt.user_id = u.id
            WHERE np.stream_id = ? AND np.ended_at IS NULL
            ORDER BY np.started_at DESC
            LIMIT 1
        ");
        $stmt->execute([$stream_id]);
        $now_playing = $stmt->fetch();
    } catch (PDOException $e) {
        error_log("Error fetching now playing: " . $e->getMessage());
        $now_playing = null;
    }
}

// Get upcoming tracks (queue)
$upcoming = [];
if ($stream_id) {
    try {
        $stmt = $pdo->prepare("
            SELECT q.*, mt.title, mt.audio_url, mt.image_url, mt.duration,
                   u.name as artist_name, u.id as artist_id
            FROM radio_stream_queue q
            JOIN music_tracks mt ON q.track_id = mt.id
            LEFT JOIN users u ON mt.user_id = u.id
            WHERE q.stream_id = ? AND q.played_at IS NULL
            ORDER BY q.priority DESC, q.vote_count DESC, q.queued_at ASC
            LIMIT 10
        ");
        $stmt->execute([$stream_id]);
        $upcoming = $stmt->fetchAll();
    } catch (PDOException $e) {
        error_log("Error fetching queue: " . $e->getMessage());
        $upcoming = [];
    }
}

$page_title = $station ? $station['station_name'] . ' - Live Radio' : 'Live Radio - SoundStudioPro';
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= htmlspecialchars($page_title) ?></title>
    <link rel="stylesheet" href="/assets/css/main.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
            color: #ffffff;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            min-height: 100vh;
            padding-bottom: 2rem;
        }
        
        .live-radio-container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 2rem;
        }
        
        .radio-header {
            text-align: center;
            margin-bottom: 3rem;
            padding-top: 2rem;
        }
        
        .station-logo {
            width: 120px;
            height: 120px;
            border-radius: 20px;
            margin: 0 auto 1.5rem;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 3rem;
            font-weight: bold;
            box-shadow: 0 10px 40px rgba(102, 126, 234, 0.3);
        }
        
        .station-logo img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            border-radius: 20px;
        }
        
        .station-name {
            font-size: 2.5rem;
            font-weight: 800;
            margin-bottom: 0.5rem;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        
        .station-call-sign {
            font-size: 1.2rem;
            color: #a0aec0;
            margin-bottom: 1rem;
        }
        
        .live-badge {
            display: inline-block;
            padding: 0.5rem 1.5rem;
            background: #ef4444;
            color: white;
            border-radius: 50px;
            font-size: 0.9rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 1px;
            animation: pulse 2s ease-in-out infinite;
            margin-bottom: 1rem;
        }
        
        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.7; }
        }
        
        .player-section {
            background: rgba(26, 26, 26, 0.8);
            border-radius: 24px;
            padding: 3rem;
            margin-bottom: 2rem;
            border: 1px solid rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(20px);
        }
        
        .now-playing {
            display: flex;
            align-items: center;
            gap: 2rem;
            margin-bottom: 2rem;
        }
        
        .track-artwork {
            width: 200px;
            height: 200px;
            border-radius: 16px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            flex-shrink: 0;
            overflow: hidden;
            box-shadow: 0 10px 40px rgba(102, 126, 234, 0.3);
        }
        
        .track-artwork img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .track-info {
            flex: 1;
        }
        
        .track-title {
            font-size: 2rem;
            font-weight: 700;
            margin-bottom: 0.5rem;
        }
        
        .track-artist {
            font-size: 1.3rem;
            color: #a0aec0;
            margin-bottom: 1rem;
        }
        
        .audio-player {
            width: 100%;
            margin-top: 1.5rem;
        }
        
        .audio-player audio {
            width: 100%;
            height: 50px;
        }
        
        .listener-count {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            color: #a0aec0;
            font-size: 1rem;
            margin-top: 1rem;
        }
        
        .listener-count strong {
            color: #667eea;
        }
        
        .voting-section {
            background: rgba(26, 26, 26, 0.6);
            border-radius: 20px;
            padding: 2rem;
            margin-top: 2rem;
        }
        
        .voting-section h3 {
            font-size: 1.5rem;
            margin-bottom: 1.5rem;
        }
        
        .upcoming-tracks {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
            gap: 1.5rem;
            margin-top: 1.5rem;
        }
        
        .track-card {
            background: rgba(26, 26, 26, 0.8);
            border-radius: 16px;
            padding: 1.5rem;
            border: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s;
            cursor: pointer;
        }
        
        .track-card:hover {
            transform: translateY(-5px);
            border-color: rgba(102, 126, 234, 0.5);
            box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
        }
        
        .track-card-artwork {
            width: 100%;
            aspect-ratio: 1;
            border-radius: 12px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin-bottom: 1rem;
            overflow: hidden;
        }
        
        .track-card-artwork img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .track-card-title {
            font-size: 1.1rem;
            font-weight: 600;
            margin-bottom: 0.5rem;
        }
        
        .track-card-artist {
            font-size: 0.9rem;
            color: #a0aec0;
            margin-bottom: 1rem;
        }
        
        .vote-button {
            width: 100%;
            padding: 0.75rem;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .vote-button:hover {
            transform: scale(1.05);
            box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
        }
        
        .vote-button.voted {
            background: #48bb78;
        }
        
        .vote-count {
            text-align: center;
            color: #667eea;
            font-weight: 600;
            margin-top: 0.5rem;
        }
        
        .no-stream {
            text-align: center;
            padding: 4rem 2rem;
        }
        
        .no-stream h2 {
            font-size: 2rem;
            margin-bottom: 1rem;
        }
        
        .no-stream p {
            color: #a0aec0;
            font-size: 1.1rem;
        }
        
        @media (max-width: 768px) {
            .now-playing {
                flex-direction: column;
                text-align: center;
            }
            
            .track-artwork {
                width: 150px;
                height: 150px;
            }
            
            .station-name {
                font-size: 1.8rem;
            }
            
            .upcoming-tracks {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <?php include __DIR__ . '/../includes/header.php'; ?>
    
    <div class="live-radio-container">
        <?php if ($station && $stream_id): ?>
            <div class="radio-header">
                <?php if ($station['logo_url']): ?>
                    <div class="station-logo">
                        <img src="<?= htmlspecialchars($station['logo_url']) ?>" alt="<?= htmlspecialchars($station['station_name']) ?>">
                    </div>
                <?php else: ?>
                    <div class="station-logo">
                        <?= strtoupper(substr($station['station_name'], 0, 2)) ?>
                    </div>
                <?php endif; ?>
                
                <div class="live-badge">🔴 LIVE</div>
                <h1 class="station-name"><?= htmlspecialchars($station['station_name']) ?></h1>
                <?php if ($station['call_sign']): ?>
                    <div class="station-call-sign"><?= htmlspecialchars($station['call_sign']) ?></div>
                <?php endif; ?>
            </div>
            
            <div class="player-section">
                <?php if ($now_playing): ?>
                    <div class="now-playing">
                        <div class="track-artwork">
                            <?php if ($now_playing['image_url']): ?>
                                <img src="<?= htmlspecialchars($now_playing['image_url']) ?>" alt="<?= htmlspecialchars($now_playing['title']) ?>">
                            <?php else: ?>
                                <div style="display: flex; align-items: center; justify-content: center; height: 100%; font-size: 3rem;">🎵</div>
                            <?php endif; ?>
                        </div>
                        <div class="track-info">
                            <h2 class="track-title"><?= htmlspecialchars($now_playing['title']) ?></h2>
                            <div class="track-artist">
                                <?php if ($now_playing['artist_name']): ?>
                                    <a href="/artists.php?id=<?= $now_playing['artist_id'] ?>" style="color: #667eea; text-decoration: none;">
                                        <?= htmlspecialchars($now_playing['artist_name']) ?>
                                    </a>
                                <?php else: ?>
                                    Unknown Artist
                                <?php endif; ?>
                            </div>
                            
                            <?php if ($now_playing['audio_url']): ?>
                                <div class="audio-player">
                                    <audio controls autoplay>
                                        <source src="<?= htmlspecialchars($now_playing['audio_url']) ?>" type="audio/mpeg">
                                        Your browser does not support the audio element.
                                    </audio>
                                </div>
                            <?php endif; ?>
                            
                            <div class="listener-count">
                                <span>👂</span>
                                <strong id="listener-count"><?= number_format($station['listener_count']) ?></strong>
                                <span>listeners</span>
                            </div>
                        </div>
                    </div>
                <?php else: ?>
                    <div style="text-align: center; padding: 2rem;">
                        <h3 style="margin-bottom: 1rem;">Stream Starting Soon...</h3>
                        <p style="color: #a0aec0;">Waiting for the next track to begin.</p>
                    </div>
                <?php endif; ?>
            </div>
            
            <?php if (count($upcoming) > 0): ?>
                <div class="voting-section">
                    <h3>🎵 Vote for Next Track</h3>
                    <div class="upcoming-tracks">
                        <?php foreach ($upcoming as $track): ?>
                            <div class="track-card" data-track-id="<?= $track['track_id'] ?>">
                                <div class="track-card-artwork">
                                    <?php if ($track['image_url']): ?>
                                        <img src="<?= htmlspecialchars($track['image_url']) ?>" alt="<?= htmlspecialchars($track['title']) ?>">
                                    <?php else: ?>
                                        <div style="display: flex; align-items: center; justify-content: center; height: 100%; font-size: 2rem;">🎵</div>
                                    <?php endif; ?>
                                </div>
                                <div class="track-card-title"><?= htmlspecialchars($track['title']) ?></div>
                                <div class="track-card-artist">
                                    <?= htmlspecialchars($track['artist_name'] ?? 'Unknown Artist') ?>
                                </div>
                                <button class="vote-button" onclick="voteForTrack(<?= $track['track_id'] ?>, <?= $stream_id ?>)">
                                    Vote
                                </button>
                                <div class="vote-count" id="votes-<?= $track['track_id'] ?>">
                                    <?= $track['vote_count'] ?> votes
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>
                </div>
            <?php endif; ?>
        <?php else: ?>
            <div class="no-stream">
                <h2>No Live Stream Available</h2>
                <p>There are currently no active radio streams. Check back soon!</p>
            </div>
        <?php endif; ?>
    </div>
    
    <script>
        const streamId = <?= $stream_id ?? 'null' ?>;
        const stationId = <?= $station_id ?? 'null' ?>;
        
        // Real-time updates using Server-Sent Events
        if (streamId) {
            const eventSource = new EventSource(`/radio/api/live/stream.php?stream_id=${streamId}`);
            
            eventSource.onmessage = function(event) {
                const data = JSON.parse(event.data);
                
                if (data.type === 'now_playing') {
                    // Update now playing track
                    location.reload(); // Simple refresh for now
                }
                
                if (data.type === 'listener_count') {
                    const countEl = document.getElementById('listener-count');
                    if (countEl) {
                        countEl.textContent = parseInt(data.count).toLocaleString();
                    }
                }
                
                if (data.type === 'vote_update') {
                    const voteEl = document.getElementById(`votes-${data.track_id}`);
                    if (voteEl) {
                        voteEl.textContent = `${data.vote_count} votes`;
                    }
                }
            };
            
            eventSource.onerror = function(error) {
                console.error('SSE error:', error);
                // Reconnect after 5 seconds
                setTimeout(() => {
                    eventSource.close();
                    location.reload();
                }, 5000);
            };
        }
        
        // Vote for track
        function voteForTrack(trackId, streamId) {
            fetch('/radio/api/live/vote.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    track_id: trackId,
                    stream_id: streamId
                })
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const button = event.target;
                    button.classList.add('voted');
                    button.textContent = 'Voted ✓';
                    button.disabled = true;
                    
                    const voteEl = document.getElementById(`votes-${trackId}`);
                    if (voteEl) {
                        voteEl.textContent = `${data.vote_count} votes`;
                    }
                } else {
                    alert(data.error || 'Failed to vote');
                }
            })
            .catch(error => {
                console.error('Vote error:', error);
                alert('Failed to vote. Please try again.');
            });
        }
        
        // Track listener connection
        if (streamId) {
            fetch('/radio/api/live/listener.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    stream_id: streamId,
                    action: 'connect'
                })
            });
            
            // Disconnect on page unload
            window.addEventListener('beforeunload', () => {
                navigator.sendBeacon('/radio/api/live/listener.php', JSON.stringify({
                    stream_id: streamId,
                    action: 'disconnect'
                }));
            });
        }
    </script>
    
    <?php include __DIR__ . '/../includes/footer.php'; ?>
</body>
</html>


CasperSecurity Mini