This commit is contained in:
Keep Creating Online committed 2025-02-23 16:32:21 -05:00
1 parent abb29c453a
commit 7592121a0b
7 files changed
+5067 -135

No files matched your search

+3
View File
@@ -1,5 +1,8 @@
node_modules/
downloads/
dist/
uploads/
temp/
saved_config.yaml
repo-context.txt
+100 -34
View File
@@ -1,16 +1,18 @@
# vitvid Torrent Seeder
# bitvid Torrent Seeder
Simple Torrent Seeder is a Node.js application that uses WebTorrent to seed torrents from the command line and provides a modern web interface to manage them. The app saves torrent metadata to a JSON file so that torrents can be resumed automatically when the server restarts. It supports adding, pausing/resuming, and removing torrents, and displays details such as progress, peer count, and upload/download amounts.
bitvid Torrent Seeder is a Node.js application that uses WebTorrent to seed torrents and provides a modern web interface for managing them. The app saves torrent metadata to a JSON file (`torrents.json`), allowing torrents to be resumed automatically when the server restarts. It supports adding, pausing/resuming, and removing torrents, and displays details such as progress, peer count, and upload/download amounts. The application can be run as a standalone server or packaged as a desktop application using Electron, providing a system tray icon for easy access.
## Features
- **Add Torrents:** Enter a magnet link to add a new torrent.
- **Active/Paused View:** See a list of active torrents and paused ones.
- **Pause/Resume:** Pause a torrent (which removes it from active seeding) and resume it later.
- **Remove Torrents:** Remove a torrent from the client and delete its files.
- **Detailed Status:** View progress, peer count, downloaded, and uploaded amounts.
- **Persistent Storage:** Torrent metadata is saved to a JSON file for persistence.
- **Add Torrents:** Add torrents via magnet links or by uploading video files.
- **Active/Paused View:** View active and paused torrents in a paginated table.
- **Pause/Resume:** Pause active torrents to stop seeding or resume paused torrents.
- **Remove Torrents:** Remove torrents and delete associated files.
- **Detailed Status:** See real-time progress, peer count, and data transfer amounts.
- **Persistent Storage:** Torrent metadata is saved in `torrents.json` for persistence across restarts.
- **Responsive UI:** A modern, desktop- and mobile-friendly interface built with Bootstrap.
- **System Tray Support (Electron):** Run the app in the background with a tray icon for quick access to the UI.
- **Nostr Integration:** Manage user profiles and authentication via Nostr.
## Prerequisites
@@ -22,8 +24,8 @@ Simple Torrent Seeder is a Node.js application that uses WebTorrent to seed torr
1. **Clone the Repository:**
```bash
git clone https://github.com/yourusername/simple-torrent-seeder.git
cd simple-torrent-seeder
git clone https://github.com/yourusername/bitvid-seeder.git
cd bitvid-seeder
```
2. **Install Dependencies:**
@@ -32,76 +34,140 @@ Simple Torrent Seeder is a Node.js application that uses WebTorrent to seed torr
npm install
```
This command installs the following packages:
- express
- webtorrent
- express-rate-limit
- winston
This command installs the necessary packages, including:
- `express`
- `webtorrent`
- `express-rate-limit`
- `winston`
- `jsonstream`
- `multer`
- `proper-lockfile`
3. **Install Electron and Electron Builder for Packaging (Optional):**
If you plan to package the app as a desktop application, install Electron and Electron Builder:
```bash
npm install electron electron-builder --save-dev
```
## Configuration
- The app uses a `config.json` file to store settings. If one does not exist, it will be created automatically with the default storage directory set to `./downloads`.
- You can change the storage directory either via the web interface under **Storage Settings** or by editing the `config.json` file directly.
- The app uses a `config.json` file to store settings, such as the storage directory for torrent files. If `config.json` does not exist, it will be created automatically with the default storage directory set to `./downloads`.
- You can change the storage directory via the web interface under **Storage Settings** or by editing `config.json` directly.
## Running the App
Start the server with:
### Running as a Server
To run the app as a standalone server, use:
```bash
node server.js
```
Then open your web browser and navigate to [http://localhost:3000](http://localhost:3000).
Then, open your web browser and navigate to [http://localhost:3000](http://localhost:3000).
### Running with Electron (Tray Icon Support)
To run the app with Electron for system tray support:
1. Ensure you have installed Electron:
```bash
npm install electron --save-dev
```
2. Start the app using:
```bash
npm run electron
```
- This will launch the app in the background with a tray icon.
- Right-click the tray icon to open the UI or quit the app.
- The UI will automatically open in your default browser on startup.
## Usage
### Adding a Torrent
- Enter a magnet link into the **Add New Torrent** form and click **Add Torrent**.
- The torrent will be added and saved to the `torrents.json` file.
- **Via Magnet Link:** Enter a magnet link into the **Add New Torrent** form and click **Add Torrent**.
- **Via File Upload:** Upload a video file to seed it directly.
### Viewing Torrents
- The active torrents are displayed in a table that shows:
- The active torrents are displayed in a table showing:
- **Name**
- **Progress**
- **Progress** (percentage)
- **Peer Count**
- **Downloaded** (in human-readable format)
- **Uploaded** (in human-readable format)
- **Downloaded** (human-readable format)
- **Uploaded** (human-readable format)
- **Status** (Active or Paused)
- The table refreshes automatically every 5 seconds.
### Pause/Resume
- **Pause:** Click the **Pause** button to stop seeding a torrent (its metadata remains saved).
- **Resume:** Click the **Resume** button to re-add a paused torrent (if files exist, it will be seeded).
- **Pause:** Click the **Pause** button to stop seeding a torrent (metadata remains saved).
- **Resume:** Click the **Resume** button to re-add a paused torrent (seeds if files exist).
### Removing a Torrent
- Click the **Remove** button to delete a torrent from the client and remove its files from disk.
- Click the **Remove** button to delete a torrent and remove its files from disk.
### Changing Storage Settings
- Update the storage directory in the **Storage Settings** form and click **Update Storage Directory**.
- Update the storage directory in the **Storage Settings** modal and click **Update Storage Directory**.
- The current storage directory is displayed below the form.
### Nostr Profile Management
- Use the circular profile button in the top-right corner to log in via Nostr.
- Once logged in, your profile avatar and name will be displayed.
## Graceful Shutdown
The application handles termination signals (SIGINT, SIGTERM) by closing the HTTP server and destroying the WebTorrent client, ensuring that all active processes are terminated properly.
The application handles termination signals (SIGINT, SIGTERM) by closing the HTTP server and destroying the WebTorrent client, ensuring all processes are terminated properly.
## Troubleshooting
- **Max Listeners Warning:**
If you receive a "MaxListenersExceededWarning" message, the default maximum has been increased by setting:
```js
import { EventEmitter } from 'events';
import { EventEmitter } from "events";
EventEmitter.defaultMaxListeners = 50;
```
at the top of the code.
- **Torrent Not Resuming:**
Ensure that the file/folder names in your downloads directory match the `name` property stored in the `torrents.json` file.
Ensure that the file/folder names in your storage directory match the `name` property stored in the `torrents.json` file.
## Packaging the Application as a Windows Executable (.exe)
To package the application as a standalone Windows executable with a system tray icon:
1. **Install Electron Builder:**
```bash
npm install electron-builder --save-dev
```
2. **Run the Build Script:**
- Open a command prompt or terminal **with administrative privileges**. On Windows, right-click Command Prompt or PowerShell and select "Run as administrator."
- Navigate to your project directory:
```bash
cd path\to\bitvid-seeder
```
- Run the build command:
```bash
npm run build
```
This will create a `dist` folder containing the executable (`bitvid-seeder.exe`) and an installer (e.g., `bitvid-seeder Setup.exe`). The executable includes the system tray icon and opens the UI in the default browser on startup.
**Note:** Running the build script with administrative privileges is necessary to handle symbolic link creation during the build process.
## License
This project is licensed under the MIT License.
This project is licensed under the MIT License.
+27
View File
@@ -0,0 +1,27 @@
import { createWindowsInstaller } from "electron-winstaller";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function main() {
try {
await createWindowsInstaller({
appDirectory: path.join(__dirname, "dist", "bitvid-seeder-win32-x64"),
outputDirectory: path.join(__dirname, "dist", "installer"),
authors: "thePR0M3TH3AN",
exe: "bitvid-seeder.exe",
setupExe: "bitvid-installer.exe",
setupIcon: path.join(__dirname, "public", "assets", "favicon.ico"),
noMsi: true,
description: "A nostr and webtorrent torrent seeder application",
});
console.log("Installer created successfully!");
} catch (error) {
console.error(`Error creating installer: ${error.message}`);
process.exit(1);
}
}
main();
+47
View File
@@ -0,0 +1,47 @@
// main.js
import { app, Tray, Menu, shell } from "electron";
import path from "path";
import { fileURLToPath } from "url";
import { startServer } from "./server.js"; // Import your server with a modification
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
let tray = null;
let serverPort = null;
app.on("ready", () => {
// Start the Express server and get the port
serverPort = startServer();
// Create the tray icon
tray = new Tray(path.join(__dirname, "public", "assets", "favicon.ico")); // Use your app icon
const contextMenu = Menu.buildFromTemplate([
{
label: "Open UI",
click: () => {
shell.openExternal(`http://localhost:${serverPort}`);
},
},
{
label: "Quit",
click: () => {
app.quit();
},
},
]);
tray.setToolTip("bitvid-seeder");
tray.setContextMenu(contextMenu);
// Optional: Open the UI in the default browser on startup
shell.openExternal(`http://localhost:${serverPort}`);
});
// Handle app quit
app.on("window-all-closed", () => {
// Do nothing; keep the app running in the tray
});
app.on("quit", () => {
// Perform any cleanup if needed
});
+4815 -72
View File
File diff suppressed because it is too large. Load diff
+43 -8
View File
@@ -1,22 +1,57 @@
{
"name": "simple-torrent-seeder",
"name": "bitvid-seeder",
"version": "1.0.0",
"main": "server.js",
"description": "A nostr and webtorrent torrent seeder application",
"author": "npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx",
"main": "main.js",
"type": "module",
"bin": "server.js",
"pkg": {
"targets": [
"node18-win-x64"
],
"outputPath": "dist",
"assets": [
"public/**/*"
]
},
"scripts": {
"start": "node server.js"
"start": "node server.js",
"electron": "electron .",
"package": "electron-packager . bitvid-seeder --platform=win32 --arch=x64 --out=dist --overwrite --asar --icon=public/assets/png/favicon.ico",
"create-installer": "node create-installer.js",
"build": "electron-builder --win --x64"
},
"build": {
"appId": "com.yourcompany.bitvidseeder",
"productName": "bitvid-seeder",
"directories": {
"output": "dist"
},
"win": {
"icon": "public/assets/png/android-chrome-512x512.png",
"target": [
"nsis"
]
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
}
},
"dependencies": {
"child_process": "^1.0.2",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"fs": "^0.0.1-security",
"jsonstream": "^1.0.3",
"JSONStream": "^1.3.5",
"multer": "^1.4.5-lts.1",
"path": "^0.12.7",
"proper-lockfile": "^4.1.2",
"url": "^0.11.4",
"webtorrent": "^2.5.19",
"winston": "^3.17.0"
},
"devDependencies": {
"electron": "^32.1.2",
"electron-builder": "^24.13.3",
"electron-packager": "^17.1.2",
"electron-winstaller": "^5.4.0"
}
}
+32 -21
View File
@@ -10,7 +10,7 @@ import path from "path";
import { fileURLToPath } from "url";
import rateLimit from "express-rate-limit";
import winston from "winston";
import JSONStream from "JSONStream";
import JSONStream from "jsonstream";
import { lock, unlock } from "proper-lockfile";
import os from "os";
import multer from "multer"; // Added for file uploads
@@ -533,25 +533,36 @@ setInterval(() => {
);
}, 60000); // Log every minute
// **Start 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);
});
// **Start Server Function**
function startServer() {
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);
return port; // Return the port immediately (it's assigned synchronously)
}
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
// **Conditionally Start Server**
if (process.argv[1] === fileURLToPath(import.meta.url)) {
startServer(); // Start server directly if run as `node server.js`
}
export { startServer }; // Export for Electron or other modules