Skip to content

fix(alldebrid): correct magnet status response model and file extraction - #1407

Merged
dreulavelle merged 5 commits into
mainfrom
fix/alldebrid-links
Jun 27, 2026
Merged

fix(alldebrid): correct magnet status response model and file extraction#1407
dreulavelle merged 5 commits into
mainfrom
fix/alldebrid-links

Conversation

@dreulavelle

@dreulavelle dreulavelle commented Jun 27, 2026

Copy link
Copy Markdown
Member

The AllDebrid v4.1/magnet/status endpoint returns a links array on each magnet, but MagnetInfo modeled it as files. Pydantic silently discarded the unknown links field, leaving files = None every time — so _get_magnet_files always returned None and instant availability never worked.

Changes (all in alldebrid.py):

  • Add AllDebridMagnetLinkEntry model matching the actual API structure (link, filename, size, files)
  • Replace MagnetInfo.files with MagnetInfo.links: list[AllDebridMagnetLinkEntry] | None
  • Make AllDebridFile.l optional (= ""), since files inside links[].files carry no l field — the link comes from the parent link_entry.link
  • Rewrite _get_magnet_files to iterate magnet.links, injecting link_entry.link into each file (and recursing into directories via the existing _add_link_to_files_recursive)

Summary by CodeRabbit

  • Bug Fixes

    • Improved AllDebrid magnet status parsing to handle missing/optional file fields more gracefully and keep link association consistent.
    • Enhanced extraction for both flat and nested magnet directory structures, returning no items for non-ready magnets or failed requests.
    • Better handling of rejected magnet uploads by surfacing the provided rejection message.
  • Tests

    • Expanded the AllDebrid downloader test suite with updated fixtures and mocked API responses to validate parsing, recursion, and ready vs. downloading torrent info.

The MagnetInfo model had a `files` field but the AllDebrid v4.1/magnet/status
API returns `links`. Pydantic silently discarded the unknown field, leaving
`files` as None and causing _get_magnet_files to always return None.

- Add AllDebridMagnetLinkEntry model matching the actual links structure
- Replace MagnetInfo.files with MagnetInfo.links
- Make AllDebridFile.l optional (files within links[].files have no l field)
- Rewrite _get_magnet_files to iterate links, injecting each link's URL into its files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@dreulavelle, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 9 minutes and 16 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d99886fd-2ed1-4532-ba93-835ae650b757

📥 Commits

Reviewing files that changed from the base of the PR and between e6084a7 and 980eabf.

📒 Files selected for processing (1)
  • src/program/services/downloaders/alldebrid.py

Walkthrough

AllDebrid magnet status models now accept compact file entries and error-info responses, file extraction follows the updated nested structure, and tests and fixtures cover the revised parsing and torrent-info behavior.

Changes

AllDebrid magnet parsing

Layer / File(s) Summary
Model updates
src/program/services/downloaders/alldebrid.py
Imports are regrouped, AllDebridFile.l defaults to an empty string, MagnetErrorInfo.magnets accepts error entries, MagnetInfo.files defaults to None, and the magnet normalization validator no longer logs debug output.
Magnet file flow
src/program/services/downloaders/alldebrid.py
_add_link_to_files_recursive falls back to the provided download link when a file link is missing, _get_magnet_files passes the full magnet.files list into the recursive helper, and add_torrent raises AllDebridError for rejected magnet responses.
Tests and fixtures
src/tests/test_alldebrid_downloader.py, src/tests/test_data/*
Fixture JSON is updated for ready and downloading magnet payloads, and the test module adds helpers plus active parsing, file-extraction, and torrent-info coverage for the new response shapes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • rivenmedia/riven#1246: Touches the same AllDebrid downloader implementation and magnet/torrent handling flow.
  • rivenmedia/riven#1374: Updates the same AllDebrid magnet normalization and file-construction logic in src/program/services/downloaders/alldebrid.py.

Suggested reviewers

  • Gaisberg

Poem

A bunny read the magnet’s tune,
With files that dance from dune to dune.
If links go missing, fallback sings,
And tests now hop through nested things. 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is substantive but does not follow the required template or include the checklist, issue reference, or Description heading. Rewrite it using the repository template: add the checklist, a Resolves issue line, and a Description section with the change summary.
Docstring Coverage ⚠️ Warning Docstring coverage is 52.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing AllDebrid magnet status parsing and file extraction.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/alldebrid-links

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/program/services/downloaders/alldebrid.py`:
- Around line 621-633: The recursive file collection in
_add_link_to_files_recursive currently skips AllDebridMagnetLinkEntry metadata
when link_entry.files is empty, causing usable magnet entries to be dropped.
Update the handling in this branch to fall back to the entry’s filename, size,
and link fields when files is missing, and make sure _get_magnet_files can still
build an AllDebridFile from AllDebridMagnetLinkEntry even without a nested files
list.
- Line 29: Ruff is flagging the API-shaped field name `l` in
`AllDebridDownloadInfo` with E741, but it should stay aligned with the upstream
payload key. Add a targeted Ruff suppression on the `l` field declaration in
`alldebrid.py` instead of renaming the attribute, so the model stays compatible
while keeping lint green.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c6f88186-c746-4869-93cf-6b7bcdd1569c

📥 Commits

Reviewing files that changed from the base of the PR and between 06f5a78 and 9fe71f5.

📒 Files selected for processing (1)
  • src/program/services/downloaders/alldebrid.py

Comment thread src/program/services/downloaders/alldebrid.py Outdated
Comment thread src/program/services/downloaders/alldebrid.py Outdated
dreulavelle and others added 3 commits June 26, 2026 21:00
- Fall back to link entry metadata when links[].files is absent or empty
- Add noqa: E741 on AllDebridFile.l to suppress ambiguous name lint;
  the field name is dictated by the upstream API payload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…traction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…bose log

- Remove AllDebridMagnetLinkEntry (was based on v4 API; v4.1 uses files)
- Restore MagnetInfo.files field (API returns files, not links)
- Simplify _get_magnet_files to call _add_link_to_files_recursive directly
- Add MagnetErrorInfo to AllDebridMagnet for invalid-magnet upload responses
- Handle MagnetErrorInfo in add_torrent with a clean error message
- Remove verbose debug log from normalize_magnets validator
- Update test fixtures to v4.1 API format (files with embedded l links)
- Rewrite tests to cover v4.1 structure and upload error handling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/program/services/downloaders/alldebrid.py (1)

612-625: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

return None inside the loop short-circuits after the first non-error magnet.

The return None on Line 625 lives in the loop body, so once the first MagnetInfo is reached (even with empty/no files) the function returns immediately and never inspects later magnets. This is fine for the single-magnet status query in practice, but if AllDebrid ever returns an error magnet followed by a valid one, ordering would matter. Consider moving the return None outside the loop for clarity/robustness.

♻️ Proposed adjustment
             for magnet in magnets:
                 if isinstance(magnet, AllDebridMagnetStatusResponse.MagnetErrorInfo):
                     continue

                 files = magnet.files

                 if files:
                     all_files: list[AllDebridFile] = []
                     self._add_link_to_files_recursive(files, "", all_files)

                     if all_files:
                         return all_files

-                return None
+            return None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/program/services/downloaders/alldebrid.py` around lines 612 - 625, The
magnet collection logic in the downloader returns None too early because the
fallback is inside the loop over magnets. Update the flow in the
magnet-processing method to only return after all entries have been checked, so
later valid magnets are still considered if earlier ones are empty or
non-usable. Keep the existing checks around
AllDebridMagnetStatusResponse.MagnetErrorInfo, magnet.files, and
_add_link_to_files_recursive, but move the None return to the end of the method.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/program/services/downloaders/alldebrid.py`:
- Around line 612-625: The magnet collection logic in the downloader returns
None too early because the fallback is inside the loop over magnets. Update the
flow in the magnet-processing method to only return after all entries have been
checked, so later valid magnets are still considered if earlier ones are empty
or non-usable. Keep the existing checks around
AllDebridMagnetStatusResponse.MagnetErrorInfo, magnet.files, and
_add_link_to_files_recursive, but move the None return to the end of the method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8524b96e-76f2-4a80-b7b9-19c8ade24969

📥 Commits

Reviewing files that changed from the base of the PR and between 3745a3d and e6084a7.

📒 Files selected for processing (4)
  • src/program/services/downloaders/alldebrid.py
  • src/tests/test_alldebrid_downloader.py
  • src/tests/test_data/alldebrid_magnet_status_one_downloading.json
  • src/tests/test_data/alldebrid_magnet_status_one_ready.json
💤 Files with no reviewable changes (1)
  • src/tests/test_data/alldebrid_magnet_status_one_downloading.json

AllDebrid rejecting an unknown hash is expected; WARNING was too noisy
for routine scraping misses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dreulavelle
dreulavelle merged commit d4e705d into main Jun 27, 2026
3 checks passed
@dreulavelle
dreulavelle deleted the fix/alldebrid-links branch June 27, 2026 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant