Live Cams

Messaging Rates Settings

Watch live streams, chat, tip, or request private shows

Start Streaming

Live Stream

LIVE

Connecting to stream...

00:00 0 viewers

Chat

0 viewers
Welcome to the chat room
`); chatWindow.document.close(); // Sync tip buttons var tipBtns = chatWindow.document.getElementById('tipBtns'); [1,5,10,25,50,100].forEach(function(a){ var btn = chatWindow.document.createElement('button'); btn.textContent = 'Tip ' + a; btn.onclick = function(){ sendTip(a); }; tipBtns.appendChild(btn); }); } // Called from pop-out window function sendChatFromPopout(msg) { if (!currentRoom) return; fetch('/api/cam/rooms/' + currentRoom.id + '/chat', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ message: msg }) }).then(function() { loadChat(currentRoom.id); }); } // Update pop-out chat when main chat refreshes var origLoadChat = loadChat; loadChat = async function(roomId) { await origLoadChat(roomId); if (chatWindow && !chatWindow.closed) { var msgs = document.getElementById('chatMessages').innerHTML; try { chatWindow.document.getElementById('chatMsgs').innerHTML = msgs; } catch(e) {} } }; async function loadPastStreams() { try { var r = await fetch('/api/cam/past'); var d = await r.json(); var streams = d.streams || []; if (!streams.length) { document.getElementById('pastStreamsSection').innerHTML = ''; return; } document.getElementById('pastStreamsSection').innerHTML = '

Past Streams

' + '
' + streams.slice(0, 20).map(function(s) { var date = s.ended_at ? new Date(s.ended_at).toLocaleDateString([], { month:'short', day:'numeric', hour:'numeric', minute:'2-digit' }) : ''; var cc = parseInt(s.chat_count) || 0; return '
' + '
' + '
' + '' + (s.title||'Stream') + '' + '
' + date + ' · ' + (s.total_minutes||0) + ' min · ' + (s.peak_viewers||0) + ' peak viewers · ' + (s.total_earned||0) + ' credits · ' + cc + ' chat messages' + '
' + '
' + (cc > 0 ? '' : '') + (s.shared_to_feed ? 'On Feed' : '') + '' + '
' + '' + '
'; }).join('') + '
'; } catch(e) {} } async function toggleChatHistory(btn, roomId) { var el = document.getElementById('chat-history-' + roomId); if (el.style.display !== 'none') { el.style.display = 'none'; btn.textContent = 'Chat'; return; } btn.textContent = 'Loading...'; try { var r = await fetch('/api/cam/rooms/' + roomId + '/chat-history'); var d = await r.json(); var msgs = d.messages || []; el.innerHTML = msgs.length ? msgs.map(function(m) { var time = new Date(m.created_at).toLocaleTimeString([], { hour:'numeric', minute:'2-digit' }); var cls = m.message_type === 'tip' ? 'border-left:3px solid var(--text);padding-left:8px;background:var(--bg-alt,#f5f5f5)' : ''; return '
' + '' + time + '' + '' + (m.sender_name||'User') + ': ' + (m.message_type === 'tip' ? 'Tipped ' + m.tip_amount + ' credits ' + m.message : m.message) + '
'; }).join('') : '

No chat messages.

'; el.style.display = 'block'; btn.textContent = 'Hide Chat'; } catch(e) { btn.textContent = 'Chat'; } } loadRooms(); loadPastStreams(); // Auto-refresh room list every 15s setInterval(loadRooms, 15000);