feat: add torrin debrid service#1014
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughAdds Torrin debrid service support: registers the service, updates config/docs, wires factory dispatch, and implements TorrinDebridService with HTTP client, magnet lifecycle methods, caching, locking, and playback resolution. ChangesTorrin Debrid Service Integration
Sequence Diagram(s)sequenceDiagram
participant Caller
participant Resolve as TorrinDebridService.resolve()
participant DistLock as DistributedLock
participant _Resolve as _resolve()
participant Cache as Playback/Failure Cache
participant Torrin as Torrin API
participant JobDetail as getRawJob()
Caller->>Resolve: resolve(playbackInfo, filename, cacheAndPlay)
Resolve->>DistLock: acquire lock for playback key
DistLock-->>Resolve: lock acquired
Resolve->>_Resolve: call _resolve()
_Resolve->>Cache: check playback-link cache
alt cached URL present
Cache-->>_Resolve: return cached signed URL
_Resolve-->>Resolve: return signed URL
else cache miss
_Resolve->>Cache: check failure cache
alt failure cached
Cache-->>_Resolve: return null (failure)
_Resolve-->>Resolve: return undefined
else not failed before
_Resolve->>_Resolve: build magnet from downloadUrl or BTIH+tr
_Resolve->>Torrin: POST /api/jobs (submit)
Torrin-->>_Resolve: job id/status
loop poll until downloaded or timeout
_Resolve->>Torrin: GET /api/jobs/{id} (status)
Torrin-->>_Resolve: job status
end
alt job downloaded
_Resolve->>JobDetail: GET /api/jobs/{id} (full job)
JobDetail->>Torrin: request job details
Torrin-->>JobDetail: full job payload with files/streams
JobDetail-->>_Resolve: parsed job
_Resolve->>_Resolve: select best matching stream URL
_Resolve->>Cache: cache signed URL
Cache-->>_Resolve: cached
_Resolve-->>Resolve: return signed URL
else job failed or timeout
_Resolve->>Cache: cache failure (null)
_Resolve-->>Resolve: return undefined
end
end
end
Resolve->>DistLock: release lock
DistLock-->>Resolve: released
Resolve-->>Caller: final signed URL or undefined
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Adds Torrin (https://torrin.app) as a builtin debrid service. Torrin is an open-source debrid that takes magnets and returns signed HTTPS streaming URLs backed by an R2-cached library. Implementation is native (talks directly to api.torrin.app) and torrent-only; usenet/hoster flows are out of scope for this PR because they require BYOK credentials configured server-side at torrin.app/app/settings. Files: - packages/core/src/debrid/torrin.ts: TorrentDebridService impl (addMagnet, addTorrent via fetch+parse-torrent->magnet, checkMagnets via batch availability, getMagnet, listMagnets, removeMagnet, resolve with poll-on-cacheAndPlay). Reuses DistributedLock, DebridFailureCache, buildResolveKey, selectFileInTorrentOrNZB to match torbox.ts conventions. - packages/core/src/debrid/index.ts: dispatch 'torrin' to TorrinDebridService. - packages/core/src/utils/constants.ts: SERVICE id, BUILTIN_SUPPORTED_SERVICES entry, SERVICE_DETAILS metadata (single apiKey credential). - packages/core/src/config/schema/services.ts: env-var description includes the new service id. - packages/docs/.../environment-variables.mdx: regenerated via gen:env-docs. Notes: - addTorrent() accepts a magnet URI, an HTTPS URL to a .torrent file, or a base64-encoded .torrent payload. The .torrent path is parsed via parse-torrent (already a workspace dep) and converted to a magnet URI before submission, since Torrin's POST /api/jobs only accepts magnets. - generateTorrentLink() is a passthrough -- Torrin returns pre-signed URLs in Job.stream_urls[].signed_url, no separate 'unrestrict' step.
c73eb94 to
b829ca4
Compare
|
The whole website seems like a vibe codded rip off of torbox.. This isn't Dave starting his 3rd service is it? (Dave being the dude who abandoned Easy debrid and debrider leaving his customer high and dry) |
lol appreciate the concern but nah, torrin is OSS AND not a copy of anything. also been building this actively for weeks with features shipping not exactly the "abandon and run" type but then i guess All Debrid is a copy of Real Debrid |
Summary
Adds Torrin as a builtin debrid service. Torrin is an open-source debrid that takes a magnet link and returns signed HTTPS streaming URLs backed by an R2-cached library —
POST /api/jobs { magnet }returns either a cached job (200) or a downloading job (202), andJob.stream_urls[].signed_urlis the player URL.This implementation is native (talks directly to
api.torrin.app) and torrent-only for this PR — Torrin's usenet/hoster paths require BYOK credentials configured server-side at torrin.app/app/settings and are out of scope here.Changes
packages/core/src/debrid/torrin.tsTorrentDebridServiceimpl:addMagnet,addTorrent(URL or base64 .torrent → magnet viaparse-torrent),checkMagnets(batch viaPOST /api/availability, per-credential cache),getMagnet,listMagnets,removeMagnet,resolvewithDistributedLock+ playback-link cache +DebridFailureCache+ poll-on-cacheAndPlay. Mirrorstorbox.ts/stremthru.tsconventions.packages/core/src/debrid/index.ts'torrin'→TorrinDebridServiceingetDebridService.packages/core/src/utils/constants.tsTORRIN_SERVICEid, added toSERVICES+BUILTIN_SUPPORTED_SERVICES, plusSERVICE_DETAILSentry (singleapiKeycredential,tr_…format).packages/core/src/config/schema/services.tstorrinto theDEFAULT_SERVICE_CREDENTIALSenv-var description.packages/docs/content/docs/configuration/environment-variables.mdxpnpm gen:env-docs.Verified
Notes for review
addTorrentaccepts magnet URIs,.torrentURLs, or base64-encoded.torrentpayloads. When a non-magnet input arrives, it's fetched (URL) or decoded (base64) and run throughparse-torrent(already a workspace dep) to extract the info hash and trackers, then re-emitted as a magnet URI before being submitted toPOST /api/jobs. Mirrors howstremthru.addTorrenthandlesplaybackInfo.downloadUrl.generateTorrentLinkis a passthrough. Torrin returns pre-signed URLs inJob.stream_urls[].signed_url; there's no separate "unrestrict" step.UNAUTHORIZED, 403 →FORBIDDEN(Torrin returns 403 on free-plan-only paid endpoints), 429 →STORE_LIMIT_EXCEEDED(slot limit reached, Torrin's plan-based concurrency cap), 5xx →INTERNAL_SERVER_ERROR/BAD_GATEWAY.(credential, hash, fileIndex, metadata)playback link cache, both honorappConfig.builtins.debrid.errorCacheTtland route through the existingCacheabstraction (Redis-aware viaappConfig.bootstrap.redisUri).BUILTIN_DOWNLOAD_POLL_INTERVAL/BUILTIN_DOWNLOAD_MAX_WAIT_TIME(the wildcard `*` defaults work fine for Torrin since cache hits return 200 on first call and only new submissions need to poll).Test plan
Summary by CodeRabbit
New Features
Improvements
Documentation