feat: add Real-Debrid API client for premium download speeds#325
feat: add Real-Debrid API client for premium download speeds#325mvanhorn wants to merge 6 commits intoSurgeDM:mainfrom
Conversation
Add a debrid package with a Real-Debrid API client that can unrestrict file hosting links to get direct download URLs. Includes host detection to check if a URL is from a supported file host (Mega, RapidGator, etc). Adds debrid settings to the configuration (enabled, provider, API key) with a new Debrid category in the TUI settings. Wiring into the probe flow will follow in a separate PR. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary Size Analysis
|
|
Cached the |
Addresses greptile P1 finding: cachedHosts and hostsCached were accessed without synchronization. Uses double-checked locking pattern to minimize lock contention on the hot path.
|
Fixed the data race on cachedHosts/hostsCached in 6f1fa3a - added sync.RWMutex with double-checked locking so concurrent IsSupported calls are safe. Regarding the other findings:
|
| func CategoryOrder() []string { | ||
| return []string{"General", "Network", "Performance", "Categories"} | ||
| return []string{"General", "Network", "Performance", "Debrid", "Categories"} | ||
| } |
There was a problem hiding this comment.
Debrid TUI tab is visible but non-functional
CategoryOrder() now includes "Debrid", so the tab appears in the settings UI. However, view_settings.go was not updated: getSettingValues has no case "Debrid" (all three fields will display as blank), and setSettingValue also has no case "Debrid" (edits will be silently discarded). The PR description explicitly promises a working TUI settings tab, but the wiring is missing.
view_settings.go needs two additions:
// in getSettingValues
case "Debrid":
values["enabled"] = m.Settings.Network.Debrid.Enabled
values["provider"] = m.Settings.Network.Debrid.Provider
values["api_key"] = m.Settings.Network.Debrid.APIKey// in setSettingValue switch
case "Debrid":
return m.setDebridSetting(key, value, meta.Type)…plus a corresponding setDebridSetting method.
Prompt To Fix With AI
This is a comment left during a code review.
Path: internal/config/settings.go
Line: 122-124
Comment:
**Debrid TUI tab is visible but non-functional**
`CategoryOrder()` now includes `"Debrid"`, so the tab appears in the settings UI. However, `view_settings.go` was not updated: `getSettingValues` has no `case "Debrid"` (all three fields will display as blank), and `setSettingValue` also has no `case "Debrid"` (edits will be silently discarded). The PR description explicitly promises a working TUI settings tab, but the wiring is missing.
`view_settings.go` needs two additions:
```go
// in getSettingValues
case "Debrid":
values["enabled"] = m.Settings.Network.Debrid.Enabled
values["provider"] = m.Settings.Network.Debrid.Provider
values["api_key"] = m.Settings.Network.Debrid.APIKey
```
```go
// in setSettingValue switch
case "Debrid":
return m.setDebridSetting(key, value, meta.Type)
```
…plus a corresponding `setDebridSetting` method.
How can I resolve this? If you propose a fix, please make it concise.Add getSettingsValues case for "Debrid" category and setDebridSetting method so the Debrid tab in settings UI is functional (was visible but non-interactive). Addresses greptile bot finding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Addressed the greptile findings in 2cb1c98 - wired up the Debrid settings tab in view_settings.go (getSettingsValues and setDebridSetting were missing). The caching and synchronization findings were already handled in the existing implementation (supportedHostsCached with RWMutex). |
Address greptile P1 findings: - Reduce supportedHostsCached TTL from 1 hour to 5 minutes for fresher host availability checks - Capture time.Now() once and reuse for consistent TTL comparisons across the read-lock and write-lock paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Checked the greptile findings against the code:
|
|



Summary
Add a Real-Debrid API client that can unrestrict file hosting links to get direct download URLs. Includes host detection and debrid settings in the TUI.
Why this matters
From the README: "Debrid Integration: Covering subscription costs so we can test and build native Debrid support" is listed as a donation goal. JDownloader has debrid support and it's a major reason power users choose it. No TUI download manager has debrid integration.
Real-Debrid unrestricts links from file hosts like Mega, RapidGator, and Uploaded, providing direct high-speed download URLs for ~$4/month.
Changes
internal/debrid/package withClientstruct wrapping the Real-Debrid REST APIUnrestrict(link)sends a URL to Real-Debrid and gets back a direct download URLSupportedHosts()fetches the list of supported file hosting domainsIsSupported(url)checks if a URL's host is debrid-eligibleDebridSettingsto config (enabled, provider, API key) with TUI settings tabWiring into the probe flow (auto-unrestrict debrid-eligible URLs) will follow in a separate PR. This PR establishes the client and settings.
Testing
All tests use mock HTTP servers, no Real-Debrid account needed:
This contribution was developed with AI assistance (Codex + Claude Code).
Greptile Summary
This PR introduces a
internal/debridpackage with a Real-Debrid API client,DebridSettingsin config, and a working Debrid tab in the TUI settings UI. Previous concerns (data race on cached hosts, live HTTP call perIsSupportedinvocation, missing TUI wiring, redundant comments) have all been addressed in follow-up commits.resetSettingToDefaultinview_settings.gois missing acase \"Debrid\"branch. Pressing the Reset key while on the Debrid settings tab callsresetSettingToDefault(\"Debrid\", key, defaults), which falls through the switch silently, so no field is ever restored to its default.Confidence Score: 4/5
Safe to merge after fixing the missing Debrid case in resetSettingToDefault; all other changes are correct.
One P1 defect remains: pressing Reset on any Debrid setting silently does nothing because resetSettingToDefault has no Debrid branch. All prior concerns from earlier review rounds are resolved. Everything else is P2 or lower.
internal/tui/view_settings.go — resetSettingToDefault function missing Debrid case
Important Files Changed
Sequence Diagram
sequenceDiagram participant TUI as TUI (view_settings) participant Client as debrid.Client participant Cache as Host Cache (RWMutex) participant RD as Real-Debrid API Note over TUI,RD: Unrestrict flow TUI->>Client: Unrestrict(link) Client->>RD: POST /unrestrict/link (Bearer token) RD-->>Client: UnrestrictResult{Download URL} Client-->>TUI: *UnrestrictResult Note over TUI,RD: IsSupported flow (with caching) TUI->>Client: IsSupported(url) Client->>Cache: RLock check cachedHosts (TTL 5m) alt cache hit Cache-->>Client: []string (cached) else cache miss Cache-->>Client: nil Client->>Cache: Lock (double-check) Client->>RD: GET /hosts/domains (no auth) RD-->>Client: []string domains Client->>Cache: store hosts + timestamp Cache-->>Client: []string end Client-->>TUI: boolComments Outside Diff (3)
internal/tui/view_settings.go, line 247-283 (link)getSettingsValues,setSettingValue, andresetSettingToDefaultall useswitch categoryblocks that handle"General","Network","Performance", and"Categories"— but none has a"Debrid"case. When the user opens the Debrid tab: values show empty, togglingenableddoes nothing, editingapi_keyis silently discarded, and Reset has no effect. The tab is visible but completely inert.The three functions need
"Debrid"cases wired tom.Settings.Network.Debrid.{Enabled,Provider,APIKey}.Prompt To Fix With AI
internal/tui/view_settings.go, line 248-283 (link)getSettingsValues,setSettingValue, andresetSettingToDefaultall dispatch on category name viaswitchstatements, but none of them have a"Debrid"case. The result is:getSettingsValues("Debrid")returns an empty map, so every Debrid setting renders as blank in the right pane.setSettingValue("Debrid", ...)falls through all cases and returnsnilwithout writing anything — user edits are silently dropped.resetSettingToDefault("Debrid", ...)is a no-op for the same reason.The tab is visible and navigable, but every interaction with it is a silent no-op. The three functions all need a
"Debrid"arm wired tom.Settings.Network.Debrid.*. For example ingetSettingsValues:And a corresponding
setDebridSetting/ reset block coveringenabled,provider, andapi_key.Prompt To Fix With AI
internal/tui/view_settings.go, line 648-709 (link)resetSettingToDefaultmissing Debrid branchresetSettingToDefaultcovers"General","Network","Performance", and"Categories"but has no"Debrid"branch. Pressing the reset-to-default key while the Debrid tab is active silently does nothing —Enabled,Provider, andAPIKeycannot be reset through the UI.A
case "Debrid"block mirroring the pattern used for other categories (reset each key to its correspondingdefaults.Network.Debrid.*value) is needed to close this gap.Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (6): Last reviewed commit: "fix: reduce host cache TTL to 5min and u..." | Re-trigger Greptile