Add P2P privacy proxy, per-user VPN, speed optimizations, and reliability - #116
Merged
Merged
Conversation
- Server-side torrent streaming proxy hides user IPs from torrent swarms - Stale-while-revalidate cache returns instant results for cached content - Doubled scraper concurrency, halved timeouts for faster stream loading - Fix tracker init race condition and fileIdx default breaking Android P2P - Dynamic subtitle translation language (was hardcoded to Greek) - Docker resource limits for Raspberry Pi safety - Graceful shutdown handlers for both addon and scraper - Fix ws/ip/path-to-regexp/send/uuid vulnerabilities via scoped overrides - Remove dead code across all debrid modules Generated with Claude Code
- Users can provide their own SOCKS5 proxy URL in the config page so torrent traffic routes through their VPN instead of the server's IP - P2P warning banner shows when no debrid service is configured, explaining IP exposure risks and how to mitigate with VPN/proxy - Proxy URL field and help text appear when Privacy Proxy is enabled - Stream labels show "VPN Proxy" when user has their own proxy configured - Torrent engines are keyed by infoHash + proxy URL to isolate per-user Generated with Claude Code
There was a problem hiding this comment.
Pull request overview
This PR adds a server-side torrent streaming “Privacy Proxy” (optionally routed through a per-user SOCKS5 proxy/VPN), alongside scraper/addon performance tuning, cache behavior improvements, and operational hardening (startup/shutdown, dependency updates, Docker config).
Changes:
- Introduces a new
/proxy/stream/:infoHash/:fileIdxendpoint andtorrent-stream-based engine pool to stream torrents via the server (with optional SOCKS5 proxy support). - Speeds up scraping and stream fetching via higher concurrency, lower timeouts, and stale-while-revalidate caching.
- Improves operational reliability via graceful shutdown handlers, dependency overrides/updates, and Docker compose resource limit configuration.
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| scraper/providers/index.js | Makes scraper concurrency/timeouts configurable and more aggressive for faster throughput. |
| scraper/package-lock.json | Updates locked dependencies (incl. brace-expansion), impacting Node engine compatibility. |
| scraper/lib/httpClient.js | Relaxes per-provider throttling to increase request rate/concurrency. |
| scraper/index.js | Adds graceful shutdown handling for the scraper service. |
| docker-compose.yml | Adds resource limit configuration for scraper/addon/redis containers. |
| addon/serverless.js | Adds a proxy streaming route for torrent HTTP streaming via the addon server. |
| addon/package.json | Adds torrent-stream and extends overrides for vulnerability mitigation. |
| addon/package-lock.json | Locks new dependency tree for torrent proxying and updated overrides. |
| addon/moch/torbox.js | Removes unused constant as part of dead-code cleanup. |
| addon/moch/realdebrid.js | Removes unused constant and helper as part of dead-code cleanup. |
| addon/moch/putio.js | Removes unused constant as part of dead-code cleanup. |
| addon/moch/premiumize.js | Removes unused constant as part of dead-code cleanup. |
| addon/moch/offcloud.js | Removes unused constant as part of dead-code cleanup. |
| addon/moch/easydebrid.js | Removes unused constant as part of dead-code cleanup. |
| addon/moch/debridlink.js | Removes unused constant as part of dead-code cleanup. |
| addon/moch/alldebrid.js | Removes unused constant as part of dead-code cleanup. |
| addon/lib/translatedSubtitles.js | Makes translation target derive from user language preferences instead of being hardcoded. |
| addon/lib/torrentProxy.js | New torrent streaming engine pool implementation with HTTP Range support. |
| addon/lib/streamInfo.js | Switches streams to proxy URLs when enabled; adjusts fileIdx behavior and labeling. |
| addon/lib/repository.js | Tweaks scraper request timeout and retries once on empty results. |
| addon/lib/landingTemplate.js | Adds landing-page UX for P2P exposure warning and proxy configuration fields. |
| addon/lib/configuration.js | Adds parsing/defaults for proxy-related configuration fields. |
| addon/lib/cache.js | Implements stale-while-revalidate caching semantics and in-flight refresh deduplication. |
| addon/index.js | Ensures trackers are initialized before listening; adds graceful shutdown cleanup for torrent engines. |
| addon/Dockerfile | Adds build dependencies to support builds with new native/tooling requirements. |
| addon/.env.example | Documents environment variables for the privacy proxy / engine limits. |
Files not reviewed (2)
- addon/package-lock.json: Generated file
- scraper/package-lock.json: Generated file
Suppressed comments (3)
addon/lib/torrentProxy.js:96
selectFile()sortsengine.filesin-place and then usesengine.files[fileIdx]. IffileIdxcomes from the original torrent file ordering, sorting mutates that ordering and can cause the wrong file to be streamed.
function selectFile(engine, fileIdx) {
const files = engine.files.sort((a, b) => b.length - a.length);
if (fileIdx != null && fileIdx < engine.files.length) {
return engine.files[fileIdx];
}
addon/lib/torrentProxy.js:104
- The torrent engine is created with an empty tracker list (
getOrCreateEngine(infoHash, [], …)), so magnet URIs are built without trackers. This can significantly slow peer discovery or fail on torrents that rely on trackers (especially when DHT is unavailable).
export async function streamTorrent(infoHash, fileIdx, req, res, proxyUrl) {
const { entry, engineKey } = getOrCreateEngine(infoHash, [], proxyUrl);
try {
addon/lib/torrentProxy.js:133
- Range handling does not validate parsed
start/endvalues (e.g., suffix ranges likebytes=-500, non-numeric values, orstart >= total). This can generate invalidContent-Range/Content-Lengthand cause errors or unexpected reads. Consider returning 416 withContent-Range: bytes */<total>for invalid ranges.
const range = req.headers.range;
if (range) {
const parts = range.replace(/bytes=/, '').split('-');
const start = parseInt(parts[0], 10);
const end = parts[1] ? parseInt(parts[1], 10) : total - 1;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
npm ci in npm 10 fails when package.json uses npm overrides — it considers overridden transitive dependency versions as "missing" from the lock file (known npm bug). Switching to npm install resolves this while still validating the dependency tree. Generated with Claude Code
This was referenced Aug 4, 2026
Closed
- Add rate limiter for proxy stream endpoint - Fix NaN validation for PROXY_MAX_ENGINES and SCRAPER_CONCURRENCY - Fix sort mutation in selectFile (copy array before sorting) - Add HTTP 416 range validation for proxy streams - Import getBestTrackers for torrent engine initialization - Add Stremio + Nuvio feature card to landing page Generated with Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
torrent-streamso user IPs never touch torrent swarms. LRU engine pool (max 3 for Raspberry Pi), HTTP Range support for seeking, optional SOCKS5 proxy for outbound connectionsws1.x→8.21.2,ip1.x→2.0.1, scoped overrides for path-to-regexp, send, uuid, tmpSERVICEconstants from all 8 debrid modules andchunkArrayfrom realdebridTest plan
npm test)npm audit— scraper: 0 vulnerabilities; addon: only unfixableipadvisory (affects all versions, used only for torrent peer discovery)Generated with Claude Code