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 5 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). |
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 adds a
internal/debridpackage with a Real-Debrid API client (Unrestrict,SupportedHosts,IsSupported), wiresDebridSettingsinto the config, and adds a working Debrid tab in the TUI settings modal. Previous concerns around the per-call HTTP round-trip, data races on the host cache, and missing TUI wiring have all been addressed in follow-up commits on the branch.resetSettingToDefaultsilently no-ops on the Debrid tab (view_settings.go:648): the function has no\"Debrid\"case, so the reset-to-default action does nothing for all three Debrid fields.view_settings.go:279): the credential is rendered unmasked in the TUI panel.Confidence Score: 4/5
Safe to merge after fixing the silent no-op in resetSettingToDefault for the Debrid tab.
One P1 defect remains: resetting Debrid settings to defaults via the UI silently does nothing because resetSettingToDefault has no Debrid branch. All prior review concerns (caching, data race, TUI wiring) have been resolved. The fix is a straightforward addition.
internal/tui/view_settings.go — resetSettingToDefault needs a Debrid case.
Security Review
internal/tui/view_settings.go): the debridapi_keyis rendered unmasked in the settings panel; an observer with terminal access (screen recording, shoulder surfing) can read the key.Important Files Changed
Unrestrict,SupportedHosts, andIsSupported; includes a properly double-checked RWMutex cache for the host list.TestIsSupporteddoes not verify that the cache prevents more than one HTTP call.DebridSettingsstruct and wires it intoNetworkSettings,GetSettingsMetadata,CategoryOrder, andDefaultSettings; clean and consistent with existing patterns.getSettingsValues,setSettingValue, andsetDebridSetting, butresetSettingToDefaulthas no Debrid case so the reset action is silently ignored on that tab.Sequence Diagram
sequenceDiagram participant TUI as TUI (view_settings) participant Config as config.Settings participant Client as debrid.Client participant Cache as In-memory cache participant RD as Real-Debrid API TUI->>Config: Read/write DebridSettings (enabled, provider, api_key) Config-->>TUI: DebridSettings values Note over TUI,Config: Future wiring (separate PR) TUI->>Client: NewClient(apiKey) Client->>Client: Unrestrict(link) Client->>RD: POST /unrestrict/link RD-->>Client: UnrestrictResult{Download: direct URL} Client->>Client: IsSupported(url) Client->>Cache: supportedHostsCached() alt cache hit (< 1h old) Cache-->>Client: []string{hosts} else cache miss Client->>RD: GET /hosts/domains RD-->>Client: []string{hosts} Client->>Cache: store + timestamp Cache-->>Client: []string{hosts} end Client-->>TUI: true/falseComments 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 (5): Last reviewed commit: "fix: wire up Debrid settings tab in TUI" | Re-trigger Greptile