mirror of
https://github.com/PR0M3TH3AN/bitvid-seeder.git
synced 2026-11-04 20:01:11 +00:00
185 lines
6.0 KiB
HTML
185 lines
6.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Simple Torrent Seeder</title>
|
|
<!-- Bootstrap CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
</head>
|
|
<body>
|
|
<div class="container my-4">
|
|
<h1 class="mb-4">Torrent Seeder</h1>
|
|
|
|
<!-- Add Torrent Form -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">Add New Torrent</div>
|
|
<div class="card-body">
|
|
<form id="addTorrentForm" class="row g-3">
|
|
<div class="col-md-9">
|
|
<input type="text" id="magnet" class="form-control" placeholder="Enter magnet link" required>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<button type="submit" class="btn btn-primary w-100">Add Torrent</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Active Torrents Table -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">Active Torrents</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table id="torrentTable" class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Progress</th>
|
|
<th>Peers</th>
|
|
<th>Downloaded</th>
|
|
<th>Uploaded</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="torrentList">
|
|
<!-- Rows are populated dynamically -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Storage Settings -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">Storage Settings</div>
|
|
<div class="card-body">
|
|
<form id="configForm" class="row g-3">
|
|
<div class="col-md-9">
|
|
<input type="text" id="storageDir" class="form-control" placeholder="Storage directory" required>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<button type="submit" class="btn btn-secondary w-100">Update Storage Directory</button>
|
|
</div>
|
|
</form>
|
|
<p id="currentStorage" class="mt-3"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Helper to format bytes -->
|
|
<script>
|
|
function formatBytes(bytes) {
|
|
if (bytes === 0) return '0 B';
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
|
|
}
|
|
</script>
|
|
|
|
<!-- JavaScript -->
|
|
<script>
|
|
async function fetchTorrents() {
|
|
try {
|
|
const res = await fetch('/torrents');
|
|
const torrents = await res.json();
|
|
const list = document.getElementById('torrentList');
|
|
list.innerHTML = '';
|
|
|
|
torrents.forEach(torrent => {
|
|
const tr = document.createElement('tr');
|
|
|
|
// Name column
|
|
const tdName = document.createElement('td');
|
|
tdName.textContent = torrent.name;
|
|
tr.appendChild(tdName);
|
|
|
|
// Progress column
|
|
const tdProgress = document.createElement('td');
|
|
tdProgress.textContent = (torrent.progress * 100).toFixed(2) + '%';
|
|
tr.appendChild(tdProgress);
|
|
|
|
// Peers column
|
|
const tdPeers = document.createElement('td');
|
|
tdPeers.textContent = torrent.numPeers;
|
|
tr.appendChild(tdPeers);
|
|
|
|
// Downloaded column
|
|
const tdDownloaded = document.createElement('td');
|
|
tdDownloaded.textContent = formatBytes(torrent.downloaded);
|
|
tr.appendChild(tdDownloaded);
|
|
|
|
// Uploaded column
|
|
const tdUploaded = document.createElement('td');
|
|
tdUploaded.textContent = formatBytes(torrent.uploaded);
|
|
tr.appendChild(tdUploaded);
|
|
|
|
// Actions column
|
|
const tdActions = document.createElement('td');
|
|
const removeBtn = document.createElement('button');
|
|
removeBtn.textContent = 'Remove';
|
|
removeBtn.className = 'btn btn-danger btn-sm';
|
|
removeBtn.onclick = async () => {
|
|
await fetch('/remove/' + torrent.infoHash, { method: 'DELETE' });
|
|
fetchTorrents();
|
|
};
|
|
tdActions.appendChild(removeBtn);
|
|
tr.appendChild(tdActions);
|
|
|
|
list.appendChild(tr);
|
|
});
|
|
} catch (error) {
|
|
console.error('Error fetching torrents:', error);
|
|
}
|
|
}
|
|
|
|
async function fetchConfig() {
|
|
try {
|
|
const res = await fetch('/config');
|
|
const config = await res.json();
|
|
document.getElementById('currentStorage').textContent = 'Current storage directory: ' + config.storageDir;
|
|
document.getElementById('storageDir').value = config.storageDir;
|
|
} catch (error) {
|
|
console.error('Error fetching config:', error);
|
|
}
|
|
}
|
|
|
|
document.getElementById('addTorrentForm').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const magnet = document.getElementById('magnet').value;
|
|
await fetch('/add', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ magnet })
|
|
});
|
|
document.getElementById('magnet').value = '';
|
|
fetchTorrents();
|
|
});
|
|
|
|
document.getElementById('configForm').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const storageDir = document.getElementById('storageDir').value;
|
|
const res = await fetch('/config', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ storageDir })
|
|
});
|
|
const result = await res.json();
|
|
document.getElementById('currentStorage').textContent = 'Current storage directory: ' + result.storageDir;
|
|
});
|
|
|
|
// Refresh the list and config every few seconds
|
|
setInterval(() => {
|
|
fetchTorrents();
|
|
fetchConfig();
|
|
}, 5000);
|
|
fetchTorrents();
|
|
fetchConfig();
|
|
</script>
|
|
|
|
<!-- Bootstrap Bundle JS -->
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
|
</body>
|
|
</html>
|