One Hat Cyber Team
Your IP :
216.73.216.55
Server IP :
209.145.58.236
Server :
Linux vmi2852635.contaboserver.net 5.14.0-570.51.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Oct 8 09:41:34 EDT 2025 x86_64
Server Software :
Apache
PHP Version :
8.1.33
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
home
/
itahukamedia
/
www
/
join2
/
View File Name :
guest.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Guest Join</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root{color-scheme:dark}*{box-sizing:border-box}body{margin:0;min-height:100vh;background:#020617;color:#fff;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;display:flex;align-items:center;justify-content:center;padding:18px}.card{width:min(980px,100%);background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.12);border-radius:18px;padding:18px;box-shadow:0 20px 80px rgba(0,0,0,.35)}h1{font-size:22px;margin:0 0 14px}.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}input,select{background:rgba(0,0,0,.32);border:1px solid rgba(255,255,255,.18);color:#fff;border-radius:12px;padding:12px;outline:none;min-width:220px}button{border:0;border-radius:12px;padding:12px 16px;font-weight:700;cursor:pointer;background:#22c55e;color:#052e16}button.secondary{background:rgba(255,255,255,.11);color:#fff;border:1px solid rgba(255,255,255,.16)}button.danger{background:#ef4444;color:#fff}button:disabled{opacity:.5;cursor:not-allowed}.status{margin-top:12px;font-size:13px;opacity:.86;white-space:pre-wrap}.grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:14px}.panel{position:relative;border:1px solid rgba(255,255,255,.12);background:#000;border-radius:14px;overflow:hidden;min-height:300px}.label{position:absolute;z-index:2;top:10px;left:10px;background:rgba(0,0,0,.62);border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:7px 10px;font-size:12px}.videoBox{width:100%;height:380px;background:#000}.hint{font-size:12px;opacity:.7;margin-top:10px}code{background:rgba(255,255,255,.08);border-radius:7px;padding:2px 6px}@media(max-width:840px){.grid{grid-template-columns:1fr}.videoBox{height:280px}} </style> </head> <body> <div class="card"> <h1>Guest Join</h1> <div id="lobby"> <div class="row"> <input id="name" placeholder="Guest name" autocomplete="name"> <input id="room" placeholder="Room / channel" value="itahuka-live"> <button id="btnJoin">Join</button> </div> <div class="hint">You may also open <code>guest.html?room=itahuka-live</code>.</div> </div> <div id="stage" style="display:none"> <div class="row"> <button id="btnGoLive">Go Live</button> <button class="secondary" id="btnMute">Mute</button> <button class="secondary" id="btnCam">Camera Off</button> <button class="danger" id="btnLeave">Leave</button> </div> <div class="grid"> <div class="panel"><div class="label">Host / Program</div><div id="hostVideo" class="videoBox"></div></div> <div class="panel"><div class="label">You</div><div id="myVideo" class="videoBox"></div></div> </div> </div> <div class="status" id="status">Ready</div> </div> <script src="https://download.agora.io/sdk/release/AgoraRTC_N.js"></script> <script> const $ = id => document.getElementById(id); const statusEl = $('status'); const params = new URLSearchParams(location.search); if (params.get('room')) $('room').value = params.get('room'); let client, localAudioTrack, localVideoTrack; let joined = false, live = false, muted = false, camOff = false; let currentChannel = ''; function status(msg){ statusEl.textContent = msg; } function clear(id){ const el=$(id); if(el) el.innerHTML=''; } function encoder(){ return { width:1280, height:720, frameRate:30, bitrateMin:800, bitrateMax:2500 }; } function ui(){ $('btnJoin').disabled = joined; $('btnGoLive').disabled = !joined || live; $('btnMute').disabled = !live; $('btnCam').disabled = !live; $('btnLeave').disabled = !joined; } async function getJoinConfig(role){ const room = ($('room').value || 'itahuka-live').trim(); const name = ($('name').value || 'Guest').trim(); const res = await fetch('token.php?role='+encodeURIComponent(role)+'&room='+encodeURIComponent(room)+'&name='+encodeURIComponent(name)+'&t='+Date.now(), {cache:'no-store'}); const j = await res.json().catch(()=>null); if(!res.ok || !j || !j.ok) throw new Error((j&&j.error)||('token.php HTTP '+res.status)); return j; } function bindEvents(){ client.on('user-published', async (user, mediaType)=>{ try{ await client.subscribe(user, mediaType); if(mediaType === 'video' && user.videoTrack){ clear('hostVideo'); user.videoTrack.play('hostVideo'); } if(mediaType === 'audio' && user.audioTrack){ user.audioTrack.play(); } }catch(e){ console.error(e); status('Subscribe error: '+(e.message||e)); } }); client.on('user-unpublished', (user, mediaType)=>{ if(mediaType === 'video') clear('hostVideo'); }); client.on('user-left', ()=> clear('hostVideo')); } async function join(){ try{ $('btnJoin').disabled = true; status('Getting room config...'); const cfg = await getJoinConfig('guest'); currentChannel = cfg.channel; client = AgoraRTC.createClient({mode:'live', codec:'vp8'}); bindEvents(); status('Connecting...'); await client.join(cfg.appId, cfg.channel, cfg.token, cfg.uid); await client.setClientRole('audience'); joined = true; live = false; $('lobby').style.display='none'; $('stage').style.display='block'; status('Joined as audience. Click Go Live to publish mic and camera.'); }catch(e){ console.error(e); joined=false; $('btnJoin').disabled=false; status('Join failed: '+(e.message||e)); } ui(); } async function goLive(){ try{ $('btnGoLive').disabled = true; status('Requesting camera/microphone...'); await client.setClientRole('host'); localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack(); localVideoTrack = await AgoraRTC.createCameraVideoTrack({encoderConfig:encoder()}); await client.publish([localAudioTrack, localVideoTrack]); clear('myVideo'); localVideoTrack.play('myVideo'); live = true; muted=false; camOff=false; $('btnMute').textContent='Mute'; $('btnCam').textContent='Camera Off'; status('Live. Operator can now see and hear you.'); }catch(e){ console.error(e); try{await client.setClientRole('audience')}catch(_){} status('Go Live failed: '+(e.message||e)); } ui(); } async function toggleMute(){ if(!localAudioTrack) return; muted=!muted; await localAudioTrack.setEnabled(!muted); $('btnMute').textContent=muted?'Unmute':'Mute'; } async function toggleCam(){ if(!localVideoTrack) return; camOff=!camOff; await localVideoTrack.setEnabled(!camOff); $('btnCam').textContent=camOff?'Camera On':'Camera Off'; } async function stopLocal(){ try{ if(localAudioTrack) await client.unpublish(localAudioTrack); }catch(_){} try{ if(localVideoTrack) await client.unpublish(localVideoTrack); }catch(_){} try{ localAudioTrack?.stop(); localAudioTrack?.close(); }catch(_){} try{ localVideoTrack?.stop(); localVideoTrack?.close(); }catch(_){} localAudioTrack=null; localVideoTrack=null; live=false; clear('myVideo'); } async function leave(){ status('Leaving...'); await stopLocal(); try{ await client?.leave(); }catch(_){} client=null; joined=false; live=false; clear('hostVideo'); $('stage').style.display='none'; $('lobby').style.display='block'; status('Ready'); ui(); } $('btnJoin').onclick=join; $('btnGoLive').onclick=goLive; $('btnMute').onclick=toggleMute; $('btnCam').onclick=toggleCam; $('btnLeave').onclick=leave; ui(); </script> </body> </html>