137 lines
3.1 KiB
Python
Executable File
137 lines
3.1 KiB
Python
Executable File
#!/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,
|
|
}
|
|
)
|