diff --git a/pytorrent/services/rtorrent.py b/pytorrent/services/rtorrent.py
index c690227..7f16502 100644
--- a/pytorrent/services/rtorrent.py
+++ b/pytorrent/services/rtorrent.py
@@ -984,9 +984,39 @@ def _tracker_int(value, default=None):
return default
+def _tracker_rows(c: ScgiRtorrentClient, torrent_hash: str) -> list[list]:
+ fields = ("t.url=", "t.is_enabled=", "t.scrape_complete=", "t.scrape_incomplete=", "t.scrape_downloaded=")
+ errors: list[str] = []
+ for args in ((torrent_hash, "", *fields), ("", torrent_hash, *fields)):
+ try:
+ rows = c.call("t.multicall", *args)
+ return [list(r) for r in (rows or [])]
+ except Exception as exc:
+ errors.append(f"t.multicall{args[:2]}: {exc}")
+ # Note: Fallback keeps the sidebar tracker filter usable on rTorrent builds without t.multicall scrape fields.
+ total = _tracker_int(_safe_tracker_call(c, "d.tracker_size", torrent_hash, 0), 0) or 0
+ rows: list[list] = []
+ for index in range(max(0, total)):
+ target = _tracker_target(torrent_hash, index)
+ url = _safe_tracker_call(c, "t.url", target, "")
+ if not url:
+ for args in ((torrent_hash, index), ("", torrent_hash, index)):
+ try:
+ url = c.call("t.url", *args)
+ break
+ except Exception:
+ continue
+ if url:
+ enabled = _safe_tracker_call(c, "t.is_enabled", target, 1)
+ rows.append([url, enabled, None, None, None])
+ if rows:
+ return rows
+ raise RuntimeError("Cannot read trackers: " + "; ".join(errors))
+
+
def torrent_trackers(profile: dict, torrent_hash: str) -> list[dict]:
c = client_for(profile)
- rows = c.t.multicall(torrent_hash, "", "t.url=", "t.is_enabled=", "t.scrape_complete=", "t.scrape_incomplete=", "t.scrape_downloaded=")
+ rows = _tracker_rows(c, torrent_hash)
trackers = []
for idx, r in enumerate(rows):
target = _tracker_target(torrent_hash, idx)
diff --git a/pytorrent/static/app.js b/pytorrent/static/app.js
index 2b31ca4..4398030 100644
--- a/pytorrent/static/app.js
+++ b/pytorrent/static/app.js
@@ -21,6 +21,7 @@
let titleSpeedEnabled = !!Number(window.PYTORRENT?.titleSpeedEnabled || 0);
let trackerFaviconsEnabled = !!Number(window.PYTORRENT?.trackerFaviconsEnabled || 0);
let trackerSummary = {hashes:{}, trackers:[], scanned:0, errors:[]};
+ let trackerSummaryStatus = 'idle';
let trackerSummarySignature = "";
let trackerSummaryTimer = null;
const BASE_TITLE = document.title || "pyTorrent";
@@ -240,13 +241,22 @@
const src=`https://${encodeURIComponent(domain).replace(/%2E/g,'.')}/favicon.ico`;
return ``;
}
+ function trackerFilterPlaceholder(){
+ if(trackerSummaryStatus==='loading') return '