read torrent seed time and ratio from qbittorrent

This commit is contained in:
lucas committed 2026-10-25 14:23:29 +01:00
1 parent 7e7a8c3af5
commit b875c1e193
2 files changed
+136 -29

No files matched your search

-29
View File
@@ -1,29 +0,0 @@
#!/bin/bash
QBT_URL="http://localhost:8080"
TRACKERS="myanonamouse|leo-test|nordicq"
API_KEY="qbt_Fw6R39WuJVY7rdhv2IXIc5n8Yfhc"
for HASH in $(
curl -s \
-H "Authorization: Bearer $API_KEY" \
"$QBT_URL/api/v2/torrents/info" \
| jq -r '.[].hash'
)
do
if curl -s \
-H "Authorization: Bearer $API_KEY" \
"$QBT_URL/api/v2/torrents/trackers?hash=$HASH" \
| jq -r '.[].url' \
| grep -Eq "$TRACKERS"
then
curl -s \
-H "Authorization: Bearer $API_KEY" \
--data "hashes=$HASH&value=true" \
"$QBT_URL/api/v2/torrents/setForceStart" \
>/dev/null
echo "Force Start: $HASH"
fi
done
+136
View File
@@ -0,0 +1,136 @@
#!/usr/bin/env python3
from datetime import timedelta
import argparse
import requests
QBT_URL = "http://192.168.0.2:8080"
API_KEY = "qbt_Fw6R39WuJVY7rdhv2IXIc5n8Yfhc"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
}
def get_torrents():
r = requests.get(
f"{QBT_URL}/api/v2/torrents/info",
headers=HEADERS,
timeout=30,
)
r.raise_for_status()
return r.json()
def get_trackers(torrent_hash):
r = requests.get(
f"{QBT_URL}/api/v2/torrents/trackers",
params={"hash": torrent_hash},
headers=HEADERS,
timeout=30,
)
r.raise_for_status()
return r.json()
def set_force_start(torrent_hash, enabled=True):
requests.post(
f"{QBT_URL}/api/v2/torrents/setForceStart",
data={
"hashes": torrent_hash,
"value": str(enabled).lower(),
},
headers=HEADERS,
timeout=30,
).raise_for_status()
def force_start_by_tracker(trackers):
"""
trackers = {
"myanonamouse": True,
"leo-test": False,
"nordicq": True,
}
"""
for torrent in get_torrents():
torrent_hash = torrent["hash"]
name = torrent["name"]
tracker_urls = " ".join(
t.get("url", "") for t in get_trackers(torrent_hash)
).lower()
for tracker, force_start in trackers.items():
if tracker.lower() in tracker_urls:
set_force_start(torrent_hash, force_start)
print(f"{name} -> force_start={force_start} (matched {tracker})")
break
def format_duration(seconds):
hours = seconds / 3600
days = seconds // 86400
return f"{days}d ({hours:.1f}h)"
def show_torrents(sort_by="name", reverse=True):
sort_keys = {
"name": lambda t: t["name"].lower(),
"ratio": lambda t: t.get("ratio", 0),
"seed_time": lambda t: t.get("seeding_time", 0),
}
torrents = sorted(
get_torrents(),
key=sort_keys[sort_by],
reverse=reverse,
)
rows = [
(
t["name"],
f"{t.get('ratio', 0):.2f}",
format_duration(t.get("seeding_time", 0)),
)
for t in torrents
]
name_w = max((len(name) for name, _, _ in rows), default=0)
ratio_w = max((len(ratio) for _, ratio, _ in rows), default=0)
for name, ratio, seed_time in rows:
print(f"{name:<{name_w}} Ratio: {ratio:>{ratio_w}} Seed Time: {seed_time}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--sort",
choices=["name", "ratio", "seed_time"],
default="name",
)
parser.add_argument(
"--force",
action="store_true",
)
parser.add_argument(
"--asc",
action="store_true",
)
args = parser.parse_args()
show_torrents(
sort_by=args.sort,
reverse=not args.asc,
)
if args.force:
force_start_by_tracker(
{
"myanonamouse": True,
"leo-test": True,
"nordicq": True,
}
)