Fix: Download to Debrid and automatic RD playback routing for torrent-URL-only indexer results
Problem
Indexers like 1337x and TorrentGalaxy (via Prowlarr) return results that contain only a .torrent file URL — no magnet link and no info hash in the search result metadata. This caused a chain of failures:
1. "Download to Debrid" always failed with "Could not resolve torrent details"
_download_to_debrid in source_select.py only checked three sources for the info hash:
source.infoHash directly
- Extracting from a magnet field
- Extracting from URL if it starts with
magnet:?
When none of these were present (Prowlarr .torrent URL results), it immediately showed the error notification without attempting to fetch the torrent file.
2. Root bug in get_magnet_from_uri
get_magnet_from_uri in debrid_utils.py already correctly downloads and parses .torrent files using extract_torrent_metadata, successfully extracting both the magnet link and info hash. However, when returning the result it discarded the magnet by returning "" instead of the extracted value:
# Before (bug):
return "", info_hash, torrent_url
# After (fix):
return magnet, info_hash, torrent_url
This caused every subsequent call to the same URL to re-fetch the torrent file — which then timed out on Prowlarr's rate-limited download proxy.
3. No automatic debrid routing after manual "Download to Debrid"
Even after successfully sending a torrent to a debrid service via the context menu, selecting the result normally always routed to Jacktorr instead of the debrid service. This happened because raw Torrent results from Prowlarr have no debridType set, so resolve_playback_url skipped the debrid path entirely and fell through to get_torrent_url.
Solution
lib/utils/debrid/debrid_utils.py
1. Fix get_magnet_from_uri to return the extracted magnet:
# Before:
return "", info_hash, torrent_url
# After:
return magnet, info_hash, torrent_url
2. Improve error visibility in get_debrid_direct_url:
except ValueError as e:
kodilog(f"Unknown debrid type: {debrid_type}: {e}")
return None
except Exception as e:
kodilog(f"get_debrid_direct_url failed: {e}")
return None
lib/gui/source_select.py
1. Add get_magnet_from_uri fallback in _download_to_debrid:
# Fallback: fetch torrent URL to extract info_hash
# (needed when indexer returns a .torrent file URL instead of a magnet)
if not info_hash and url:
kodilog(f"Fetching torrent URL to extract info_hash: {url}")
_, info_hash, _ = get_magnet_from_uri(url)
if info_hash:
info_hash = info_hash.lower()
2. Cache the extracted hash by IMDB ID after successful extraction:
# Cache the hash keyed by IMDB ID for future automatic playback routing
try:
from lib.utils.general.utils import set_cached
imdb_id = (self.item_information.get("ids") or {}).get("imdb_id", "")
if imdb_id:
set_cached(info_hash, f"rd_hash_{imdb_id}")
kodilog(f"Cached RD hash for {imdb_id}: {info_hash[:12]}")
except Exception:
pass
3. Add get_magnet_from_uri to imports:
from lib.utils.debrid.debrid_utils import add_source_to_debrid, get_source_status, get_magnet_from_uri
lib/utils/player/utils.py
Add automatic debrid routing in resolve_playback_url:
When a Torrent result has no debridType, check if its hash exists in the user's debrid account using the cached IMDB ID lookup. If found, route directly to debrid instead of Jacktorr:
# If no debrid_type, check if hash exists in debrid account
if not debrid_type:
info_hash = data.get("info_hash", "") or ""
if not info_hash:
magnet = data.get("magnet", "") or ""
if magnet:
info_hash = get_info_hash_from_magnet(magnet).lower()
# Check cache for hash stored during "Download to Debrid" (keyed by IMDB ID)
if not info_hash:
try:
from lib.utils.general.utils import get_cached
ids = data.get("ids") or {}
imdb_id = ids.get("imdb_id", "") if isinstance(ids, dict) else ""
if imdb_id:
cached_hash = get_cached(f"rd_hash_{imdb_id}")
if cached_hash and isinstance(cached_hash, str):
info_hash = cached_hash
kodilog(f"Using cached debrid hash for {imdb_id}: {info_hash[:12]}")
except Exception as e:
kodilog(f"Debrid hash cache lookup failed: {e}")
if info_hash:
try:
from lib.utils.general.utils import is_rd_enabled
if is_rd_enabled():
from lib.clients.debrid.realdebrid import RealDebridHelper
torrent_info = RealDebridHelper().client.get_available_torrent(info_hash)
if torrent_info:
kodilog(f"Hash {info_hash[:12]} found in debrid account, routing to debrid")
data["debrid_type"] = "RealDebrid"
data["info_hash"] = info_hash
debrid_url = get_debrid_url(data, "RealDebrid", is_pack)
if debrid_url:
return data
except Exception as e:
kodilog(f"Debrid account check failed: {e}")
User Workflow (after fix)
For rare/low-seeder torrents found via Prowlarr that are not yet cached on a debrid service:
- Find the result in Jacktook source select screen
- Open context menu → "Download to Debrid"
- Wait for "Added to [debrid] cloud" notification
- Wait for the debrid service to finish downloading the torrent
- Select the result normally → plays automatically via debrid CDN
The hash is cached by IMDB ID so subsequent plays require no extra steps.
Tested On
- LibreELEC nightly (RPi5.aarch64)
- Jacktook v1.7.1
- Prowlarr indexers: 1337x, TorrentGalaxy
Fix: Download to Debrid and automatic RD playback routing for torrent-URL-only indexer results
Problem
Indexers like 1337x and TorrentGalaxy (via Prowlarr) return results that contain only a
.torrentfile URL — no magnet link and no info hash in the search result metadata. This caused a chain of failures:1. "Download to Debrid" always failed with "Could not resolve torrent details"
_download_to_debridinsource_select.pyonly checked three sources for the info hash:source.infoHashdirectlymagnet:?When none of these were present (Prowlarr
.torrentURL results), it immediately showed the error notification without attempting to fetch the torrent file.2. Root bug in
get_magnet_from_uriget_magnet_from_uriindebrid_utils.pyalready correctly downloads and parses.torrentfiles usingextract_torrent_metadata, successfully extracting both the magnet link and info hash. However, when returning the result it discarded the magnet by returning""instead of the extracted value:This caused every subsequent call to the same URL to re-fetch the torrent file — which then timed out on Prowlarr's rate-limited download proxy.
3. No automatic debrid routing after manual "Download to Debrid"
Even after successfully sending a torrent to a debrid service via the context menu, selecting the result normally always routed to Jacktorr instead of the debrid service. This happened because raw Torrent results from Prowlarr have no
debridTypeset, soresolve_playback_urlskipped the debrid path entirely and fell through toget_torrent_url.Solution
lib/utils/debrid/debrid_utils.py1. Fix
get_magnet_from_urito return the extracted magnet:2. Improve error visibility in
get_debrid_direct_url:lib/gui/source_select.py1. Add
get_magnet_from_urifallback in_download_to_debrid:2. Cache the extracted hash by IMDB ID after successful extraction:
3. Add
get_magnet_from_urito imports:lib/utils/player/utils.pyAdd automatic debrid routing in
resolve_playback_url:When a Torrent result has no
debridType, check if its hash exists in the user's debrid account using the cached IMDB ID lookup. If found, route directly to debrid instead of Jacktorr:User Workflow (after fix)
For rare/low-seeder torrents found via Prowlarr that are not yet cached on a debrid service:
The hash is cached by IMDB ID so subsequent plays require no extra steps.
Tested On