Format: text/html
⬇ Download File (4.6 KB)
   1  <!DOCTYPE html>
   2  <html lang="en">
   3  <head>
   4    <meta charset="UTF-8" />
   5    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   6    <title>🎮 Magnet Streamer</title>
   7    <script src="https://cdn.socket.io/4.6.1/socket.io.min.js"></script>
   8    <style>
   9      body {
  10        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  11        background: linear-gradient(to right, #141e30, #243b55);
  12        color: white;
  13        text-align: center;
  14        padding: 40px 20px;
  15      }
  16      h1 {
  17        font-size: 2.5em;
  18        margin-bottom: 20px;
  19      }
  20      form {
  21        margin-bottom: 30px;
  22      }
  23      input[type="text"] {
  24        width: 70%;
  25        padding: 16px;
  26        font-size: 16px;
  27        border: none;
  28        border-radius: 8px;
  29        margin-bottom: 16px;
  30        box-shadow: 0 0 12px rgba(0,0,0,0.3);
  31      }
  32      button {
  33        padding: 14px 32px;
  34        font-size: 16px;
  35        background-color: #00c853;
  36        color: white;
  37        border: none;
  38        border-radius: 8px;
  39        cursor: pointer;
  40      }
  41      #status {
  42        margin-top: 30px;
  43        font-size: 16px;
  44      }
  45      #log {
  46        background: rgba(0, 0, 0, 0.5);
  47        border-radius: 6px;
  48        padding: 14px;
  49        max-width: 900px;
  50        margin: 30px auto;
  51        font-family: monospace;
  52        font-size: 14px;
  53        text-align: left;
  54        white-space: pre-line;
  55        max-height: 350px;
  56        overflow-y: auto;
  57        overflow-x: auto;
  58        box-shadow: inset 0 0 6px rgba(255,255,255,0.1);
  59      }
  60      video {
  61        margin-top: 30px;
  62        width: 80%;
  63        max-width: 900px;
  64        border-radius: 10px;
  65        box-shadow: 0 0 20px rgba(0, 0, 0, 0.4);
  66      }
  67    </style>
  68  </head>
  69  <body>
  70    <h1>🎮 Stream a Magnet Link</h1>
  71    <form id="magnetForm">
  72      <input type="text" id="magnetInput" name="magnet" placeholder="Paste magnet link here" required />
  73      <br />
  74      <button type="submit">▶️ Play</button>
  75    </form>
  76    <div id="status">⏳ Preparing...</div>
  77    <div id="log"></div>
  78    <div id="videoContainer"></div>
  79    <script>
  80      const form = document.getElementById('magnetForm');
  81      const input = document.getElementById('magnetInput');
  82      const statusEl = document.getElementById("status");
  83      const logEl = document.getElementById("log");
  84      const videoContainer = document.getElementById("videoContainer");
  85      let magnet = null;
  86      const socket = io();
  87  
  88      socket.on("log_update", (data) => {
  89        if (data.magnet === magnet && logEl) {
  90          logEl.textContent += "\n" + data.message;
  91          logEl.scrollTop = logEl.scrollHeight;
  92        }
  93      });
  94  
  95      form.addEventListener('submit', async function (e) {
  96        e.preventDefault();
  97        magnet = input.value.trim();
  98        if (!magnet.startsWith("magnet:?")) {
  99          alert("Please enter a valid magnet link");
 100          return;
 101        }
 102        const res = await fetch('/', {
 103          method: 'POST',
 104          headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 105          body: new URLSearchParams({ magnet })
 106        });
 107        if (!res.ok) {
 108          statusEl.textContent = "❌ Failed to submit magnet link.";
 109          return;
 110        }
 111        window.history.pushState({}, '', `/player?magnet=${encodeURIComponent(magnet)}`);
 112        statusEl.textContent = "⏳ Download started...";
 113        pollStatus();
 114      });
 115  
 116      window.addEventListener('DOMContentLoaded', () => {
 117        const params = new URLSearchParams(window.location.search);
 118        if (params.has("magnet")) {
 119          magnet = params.get("magnet");
 120          statusEl.textContent = "⏳ Checking torrent status...";
 121          pollStatus();
 122        }
 123      });
 124  
 125      async function pollStatus() {
 126        try {
 127          const res = await fetch(`/status?magnet=${encodeURIComponent(magnet)}`);
 128          const data = await res.json();
 129  
 130          const pct = data.progress ?? 0;
 131          const peers = data.peers ?? 0;
 132          const rate = data.downloadRate ?? 0;
 133          statusEl.textContent = `📦 ${pct}% complete | Peers: ${peers} | DL: ${rate} KB/s`;
 134  
 135          if (data.ready && data.meta && Array.isArray(data.meta.files) && !document.querySelector("video")) {
 136            const fileName = data.meta.files.find(f => f.name.endsWith('.mp4') || f.name.endsWith('.mkv') || f.name.endsWith('.avi'))?.name;
 137            if (fileName) {
 138              const video = document.createElement("video");
 139              video.src = `/stream?magnet=${encodeURIComponent(magnet)}&file=${encodeURIComponent(fileName)}`;
 140              video.controls = true;
 141              video.autoplay = true;
 142              videoContainer.appendChild(video);
 143              video.scrollIntoView({ behavior: 'smooth' });
 144            }
 145          } else {
 146            setTimeout(pollStatus, 2000);
 147          }
 148        } catch (err) {
 149          statusEl.textContent = "⚠️ Error checking download status.";
 150        }
 151      }
 152    </script>
 153  </body>
 154  </html>
 155