This commit is contained in:
thePR0M3TH3AN committed 2025-02-16 11:10:14 -05:00
1 parent 47c2d24d28
commit fabccd25ca
7 files changed
+3937

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
node_modules/
downloads/
saved_config.yaml
repo-context.txt
+3
View File
@@ -0,0 +1,3 @@
{
"storageDir": "/home/user/Documents/simple-torrent-seeder/downloads"
}
+3301
View File
File diff suppressed because it is too large. Load diff
+15
View File
@@ -0,0 +1,15 @@
{
"name": "simple-torrent-seeder",
"version": "1.0.0",
"main": "server.js",
"type": "module",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.2",
"express-rate-limit": "^7.5.0",
"webtorrent": "^2.5.19",
"winston": "^3.17.0"
}
}
+184
View File
@@ -0,0 +1,184 @@
<!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>
+267
View File
@@ -0,0 +1,267 @@
import { EventEmitter } from 'events';
EventEmitter.defaultMaxListeners = 50;
import express from 'express';
import WebTorrent from 'webtorrent';
import fs from 'fs';
import { promises as fsPromises } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import rateLimit from 'express-rate-limit';
import winston from 'winston';
// Set up Winston logger
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(
({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`
)
),
transports: [new winston.transports.Console()]
});
const app = express();
const port = process.env.PORT || 3000;
const client = new WebTorrent();
// Increase max listeners for the client to avoid warnings (if needed)
client.setMaxListeners(50);
// ES module __dirname workaround
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Rate limiting middleware (100 requests per minute per IP)
const limiter = rateLimit({
windowMs: 60 * 1000,
max: 100
});
app.use(limiter);
// Serve static files and parse JSON bodies
app.use(express.static('public'));
app.use(express.json());
// Load configuration from config.json
const CONFIG_FILE = path.join(__dirname, 'config.json');
let config = { storageDir: path.join(__dirname, 'downloads') };
try {
if (fs.existsSync(CONFIG_FILE)) {
const configData = fs.readFileSync(CONFIG_FILE, 'utf-8');
config = JSON.parse(configData);
// Resolve storageDir relative to __dirname
config.storageDir = path.resolve(__dirname, config.storageDir);
} else {
fs.writeFileSync(CONFIG_FILE, JSON.stringify({ storageDir: './downloads' }, null, 2));
}
} catch (err) {
logger.error('Error reading config file, using default config: ' + err);
}
let STORAGE_DIR = config.storageDir;
if (!fs.existsSync(STORAGE_DIR)) {
fs.mkdirSync(STORAGE_DIR, { recursive: true });
}
// JSON file to store torrent metadata
const TORRENTS_FILE = path.join(__dirname, 'torrents.json');
let savedTorrents = [];
try {
if (fs.existsSync(TORRENTS_FILE)) {
const data = fs.readFileSync(TORRENTS_FILE, 'utf-8');
savedTorrents = JSON.parse(data);
logger.info(`Loaded saved torrents: ${JSON.stringify(savedTorrents)}`);
} else {
logger.info('No torrents.json file found. Starting with an empty list.');
}
} catch (err) {
logger.error('Error loading torrents file: ' + err);
}
function saveTorrents() {
try {
fs.writeFileSync(TORRENTS_FILE, JSON.stringify(savedTorrents, null, 2));
} catch (err) {
logger.error('Error saving torrents file: ' + err);
}
}
// Helper: Check if a path exists asynchronously
async function pathExists(p) {
try {
await fsPromises.access(p);
return true;
} catch {
return false;
}
}
// Load saved torrents concurrently on startup.
// For each saved torrent, if the expected file/folder exists, we seed from that location;
// otherwise, we add the torrent to download.
async function loadSavedTorrents() {
await Promise.all(
savedTorrents.map(async torrentData => {
const torrentPath = path.join(STORAGE_DIR, torrentData.name);
const exists = await pathExists(torrentPath);
try {
if (exists) {
// If the file exists, seed it to keep it active.
client.seed(torrentPath, { name: torrentData.name, keepSeeding: true }, torrent => {
logger.info(`Seeding torrent from existing files: ${torrent.infoHash}`);
});
} else {
// Otherwise, add the torrent to download its files.
client.add(torrentData.magnet, { path: STORAGE_DIR, keepSeeding: true }, torrent => {
logger.info(`Downloading torrent: ${torrent.infoHash}`);
});
}
} catch (err) {
logger.error('Error loading saved torrent on startup: ' + err);
}
})
);
}
loadSavedTorrents();
// GET /config - Return current storage configuration
app.get('/config', (req, res) => {
res.json({ storageDir: STORAGE_DIR });
});
// POST /config - Update storage directory (with input validation)
app.post('/config', (req, res) => {
const { storageDir } = req.body;
if (!storageDir || typeof storageDir !== 'string') {
return res.status(400).json({ error: 'Invalid storageDir provided' });
}
try {
STORAGE_DIR = path.resolve(__dirname, storageDir);
config.storageDir = STORAGE_DIR;
if (!fs.existsSync(STORAGE_DIR)) {
fs.mkdirSync(STORAGE_DIR, { recursive: true });
}
fs.writeFileSync(CONFIG_FILE, JSON.stringify({ storageDir }, null, 2));
res.json({ message: 'Config updated', storageDir: STORAGE_DIR });
} catch (err) {
logger.error('Error updating config: ' + err);
res.status(500).json({ error: 'Error updating config' });
}
});
// POST /add - Add a new torrent (with basic validation and duplicate check)
// The keepSeeding option ensures that the torrent remains active.
app.post('/add', (req, res) => {
const { magnet } = req.body;
if (!magnet || typeof magnet !== 'string') {
return res.status(400).json({ error: 'No valid magnet link provided' });
}
if (!magnet.startsWith('magnet:?')) {
return res.status(400).json({ error: 'Invalid magnet link format' });
}
// Check if the torrent already exists in saved metadata.
if (savedTorrents.some(t => t.magnet === magnet)) {
logger.info('Attempted to add duplicate torrent.');
return res.status(409).json({ error: 'Torrent already added.' });
}
try {
client.add(magnet, { path: STORAGE_DIR, keepSeeding: true }, torrent => {
logger.info(`Torrent added: ${torrent.infoHash}`);
const torrentData = {
magnet,
infoHash: torrent.infoHash,
name: torrent.name
};
savedTorrents.push(torrentData);
saveTorrents();
res.json(torrentData);
});
} catch (err) {
logger.error('Error adding torrent: ' + err);
res.status(500).json({ error: 'Error adding torrent' });
}
});
// GET /torrents - List active torrents with extra info
app.get('/torrents', (req, res) => {
try {
const torrents = client.torrents.map(t => ({
infoHash: t.infoHash,
name: t.name,
progress: t.progress,
numPeers: t.numPeers,
downloaded: t.downloaded, // in bytes
uploaded: t.uploaded // in bytes
}));
logger.info('GET /torrents returning: ' + JSON.stringify(torrents));
res.json(torrents);
} catch (err) {
logger.error('Error listing torrents: ' + err);
res.status(500).json({ error: 'Error listing torrents' });
}
});
// DELETE /remove/:infoHash - Remove a torrent
app.delete('/remove/:infoHash', (req, res) => {
const infoHash = req.params.infoHash;
if (!infoHash || typeof infoHash !== 'string') {
return res.status(400).json({ error: 'Invalid infoHash' });
}
const torrent = client.get(infoHash);
const savedData = savedTorrents.find(t => t.infoHash === infoHash);
// Use the torrent's name if available; otherwise, use saved metadata.
const torrentName = (torrent && torrent.name) || (savedData && savedData.name);
if (!torrentName) {
return res.status(400).json({ error: 'Torrent name not found' });
}
try {
client.remove(infoHash, { destroyStore: true }, async err => {
if (err) {
logger.error('Error removing torrent: ' + err);
return res.status(500).json({ error: 'Error removing torrent' });
}
savedTorrents = savedTorrents.filter(t => t.infoHash !== infoHash);
saveTorrents();
const torrentPath = path.join(STORAGE_DIR, torrentName);
if (await pathExists(torrentPath)) {
try {
await fsPromises.rm(torrentPath, { recursive: true, force: true });
} catch (rmErr) {
logger.error('Error removing torrent files: ' + rmErr);
}
}
logger.info(`Torrent removed: ${infoHash}`);
res.json({ message: 'Torrent removed' });
});
} catch (err) {
logger.error('Error processing removal: ' + err);
res.status(500).json({ error: 'Error processing removal' });
}
});
// Start the server
const server = app.listen(port, () => {
logger.info(`Server running on http://localhost:${port}`);
});
// Graceful shutdown
function shutdown() {
logger.info('Shutting down server...');
server.close(() => {
logger.info('HTTP server closed.');
client.destroy(err => {
if (err) {
logger.error('Error destroying WebTorrent client: ' + err);
} else {
logger.info('WebTorrent client destroyed.');
}
process.exit(0);
});
});
}
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
+162
View File
@@ -0,0 +1,162 @@
[
{
"magnet": "magnet:?xt=urn:btih:0b0176838873aa20b1d16e15f77bd4e4aa36a706&dn=bitvid-logo-loop.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "0b0176838873aa20b1d16e15f77bd4e4aa36a706",
"name": "bitvid-logo-loop.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:846b56e6ac935e02a6047dc9369129c3bf013822&dn=Alien+Plexus+in+Cinema+4D.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "846b56e6ac935e02a6047dc9369129c3bf013822",
"name": "Alien Plexus in Cinema 4D.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:a92964583d6bd03b5a420a474a96f2b47d19fd43&dn=SeedSigner_SingleSig_Guide.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "a92964583d6bd03b5a420a474a96f2b47d19fd43",
"name": "SeedSigner_SingleSig_Guide.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:733aadb6a5ecef19890a78fb2251761a5c31a2b3&dn=Cinema+4D+Modular+Moving+Belt+System.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "733aadb6a5ecef19890a78fb2251761a5c31a2b3",
"name": "Cinema 4D Modular Moving Belt System.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:75b295c6ab1c7c2d61860b7a6273692e82981ab8&dn=Brementown+Musicians+UB+Iwerks+ComiColor.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "75b295c6ab1c7c2d61860b7a6273692e82981ab8",
"name": "Brementown Musicians UB Iwerks ComiColor.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:88594aaacbde40ef3e2510c47374ec0aa396c08e&dn=bbb_sunflower_1080p_30fps_normal.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=http%3A%2F%2Fdistribution.bbb3d.renderfarming.net%2Fvideo%2Fmp4%2Fbbb_sunflower_1080p_30fps_normal.mp4",
"infoHash": "88594aaacbde40ef3e2510c47374ec0aa396c08e",
"name": "bbb_sunflower_1080p_30fps_normal.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:2fbfaa29267664d476dbdde7aba651848866ce26&dn=Cinema+4D+Demo+Reel+2016.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "2fbfaa29267664d476dbdde7aba651848866ce26",
"name": "Cinema 4D Demo Reel 2016.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:f1935383c133210aa91d4d0797ed00a37b71695f&dn=Low+Poly+Train+Animation.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "f1935383c133210aa91d4d0797ed00a37b71695f",
"name": "Low Poly Train Animation.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:836242885c0556348ab30843ae58f19d2062031f&dn=Modular+Conveyor+Belt+Cinema+4d.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "836242885c0556348ab30843ae58f19d2062031f",
"name": "Modular Conveyor Belt Cinema 4d.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:b0c791fc84709e8fc32139524e6dde1490688f7e&dn=Jet+Engine+In+Cinema+4D+with+TurbulenceFD.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "b0c791fc84709e8fc32139524e6dde1490688f7e",
"name": "Jet Engine In Cinema 4D with TurbulenceFD.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:d018504190917ae2e263ed59b78faed939ed8541&dn=Cinema+4D+Fire+Pit.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "d018504190917ae2e263ed59b78faed939ed8541",
"name": "Cinema 4D Fire Pit.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:34e609103acd9015e15abfb6b4a45787bf53e23d&dn=The+Grid+(Cinema+4D+Mograph).mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "34e609103acd9015e15abfb6b4a45787bf53e23d",
"name": "The Grid (Cinema 4D Mograph).mp4"
},
{
"magnet": "magnet:?xt=urn:btih:96846efcda07c86f07b13c7f9435a5074a2c5013&dn=Cinema+4D+Fire+Pit+Final+Render.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "96846efcda07c86f07b13c7f9435a5074a2c5013",
"name": "Cinema 4D Fire Pit Final Render.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:0ed417874545b09b95b9349c5d3cbadafa4232e8&dn=Alien+Planet+Ring+Animation+Cinema+4D.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "0ed417874545b09b95b9349c5d3cbadafa4232e8",
"name": "Alien Planet Ring Animation Cinema 4D.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:9465ae875afa17e59d273c9782c6b69e22c0ad36&dn=Alien+Planet+In+Cinema+4D.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "9465ae875afa17e59d273c9782c6b69e22c0ad36",
"name": "Alien Planet In Cinema 4D.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:84a66806f990a77474120977755c1aab943e32d1&dn=Low+Poly+Portrait+-+Speed+Art.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "84a66806f990a77474120977755c1aab943e32d1",
"name": "Low Poly Portrait - Speed Art.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:b81fb49e494974cc4e099d284db7d3724f16eeae&dn=_the+Oven+Balls_+Cinema+4D+Camera+Projection+Mapping.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "b81fb49e494974cc4e099d284db7d3724f16eeae",
"name": "_the Oven Balls_ Cinema 4D Camera Projection Mapping.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:78e1e2fc3ec7edeb99ac3235a3e57e73dd9503b3&dn=_The+Oven_++Test.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "78e1e2fc3ec7edeb99ac3235a3e57e73dd9503b3",
"name": "_The Oven_ Test.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:8e321597d1aaac1799219ac353cc8f64dfa76c54&dn=Mocha-Cola+Package+Design+Cinema+4D.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "8e321597d1aaac1799219ac353cc8f64dfa76c54",
"name": "Mocha-Cola Package Design Cinema 4D.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:b352b54254c97765f276e28ffa37ceff3d010187&dn=3D+Animated+Planet+Cloud+with+Cinema+4D+(no+plugins).mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "b352b54254c97765f276e28ffa37ceff3d010187",
"name": "3D Animated Planet Cloud with Cinema 4D (no plugins).mp4"
},
{
"magnet": "magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=Sintel&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.fastcast.nz&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F",
"infoHash": "08ada5a7a6183aae1e09d831df6748d566095a10",
"name": "Sintel"
},
{
"magnet": "magnet:?xt=urn:btih:12cbeee588f9c5486526759de8e4ee5c8135e214&dn=bb_minnie_the_moocher_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "12cbeee588f9c5486526759de8e4ee5c8135e214",
"name": "bb_minnie_the_moocher_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:c80d2fb6e86f3244a646a533b430b95f00224974&dn=Popeye_Assault_and_Flattery_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "c80d2fb6e86f3244a646a533b430b95f00224974",
"name": "Popeye_Assault_and_Flattery_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:9fb39a1a4a598271f6f6be7ab8fb3fa83ce3b488&dn=woody_woodpecker_pantry_panic_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "9fb39a1a4a598271f6f6be7ab8fb3fa83ce3b488",
"name": "woody_woodpecker_pantry_panic_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:93efbbf0d639545a130079e8acaa2d0c329ced86&dn=PopeyeAliBaba_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "93efbbf0d639545a130079e8acaa2d0c329ced86",
"name": "PopeyeAliBaba_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:5f665051d91d06dca147af6b9bfbcc43873b1640&dn=superman_the_mechanical_monsters_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "5f665051d91d06dca147af6b9bfbcc43873b1640",
"name": "superman_the_mechanical_monsters_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:940f031cef17dea3392b0a6ad454d9faac0a0e5f&dn=Popeye_meetsSinbadtheSailor_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "940f031cef17dea3392b0a6ad454d9faac0a0e5f",
"name": "Popeye_meetsSinbadtheSailor_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:742aadd563de11fb69938354e6ae492b1dd5a354&dn=Popeye_forPresident_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "742aadd563de11fb69938354e6ae492b1dd5a354",
"name": "Popeye_forPresident_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:52041e146267ec9fb63fc8441571a6e82fc57ad9&dn=spree_lunch_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "52041e146267ec9fb63fc8441571a6e82fc57ad9",
"name": "spree_lunch_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:3d0ecc6bc869dbea152a74ba0d94f9539da2cff1&dn=Popeye_Cookin_with_Gags_512kb.mp4&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "3d0ecc6bc869dbea152a74ba0d94f9539da2cff1",
"name": "Popeye_Cookin_with_Gags_512kb.mp4"
},
{
"magnet": "magnet:?xt=urn:btih:6a02592d2bbc069628cd5ed8a54f88ee06ac0ba5&dn=CosmosLaundromatFirstCycle&tr=http%3A%2F%2Fbt1.archive.org%3A6969%2Fannounce&tr=http%3A%2F%2Fbt2.archive.org%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=http%3A%2F%2Fia601508.us.archive.org%2F14%2Fitems%2F&ws=http%3A%2F%2Fia801508.us.archive.org%2F14%2Fitems%2F&ws=https%3A%2F%2Farchive.org%2Fdownload%2F",
"infoHash": "6a02592d2bbc069628cd5ed8a54f88ee06ac0ba5",
"name": "CosmosLaundromatFirstCycle"
},
{
"magnet": "magnet:?xt=urn:btih:02767050e0be2fd4db9a2ad6c12416ac806ed6ed&dn=tears_of_steel_1080p.webm&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com",
"infoHash": "02767050e0be2fd4db9a2ad6c12416ac806ed6ed",
"name": "tears_of_steel_1080p.webm"
}
]