2024-11-08 15:04:23 +01:00
|
|
|
# /// script
|
|
|
|
# dependencies = [
|
|
|
|
# "qbittorrent-api",
|
|
|
|
# "docopt",
|
|
|
|
# "rich",
|
|
|
|
# ]
|
|
|
|
# ///
|
2024-08-06 03:14:16 +02:00
|
|
|
|
|
|
|
"""update_tracker.py
|
|
|
|
|
|
|
|
Description:
|
|
|
|
This script collects infohashes of all torrents in each qBittorrent instance,
|
|
|
|
updates opentracker, and reannounces all torrents to their trackers.
|
|
|
|
|
|
|
|
Expectations:
|
|
|
|
- A JSON qBittorrent authentication file at ~/.config/qbittorrent_auth.json
|
2024-10-15 00:07:17 +02:00
|
|
|
- SSH pubkey access to torrent tracker server
|
2024-08-06 03:14:16 +02:00
|
|
|
- rsync installed on the host system running this script
|
|
|
|
|
|
|
|
Usage:
|
2024-11-02 08:19:37 +01:00
|
|
|
update_tracker.py (--add-tracker DOMAIN)
|
2024-08-06 03:14:16 +02:00
|
|
|
update_tracker.py -h
|
|
|
|
|
|
|
|
Options:
|
2024-10-15 00:07:17 +02:00
|
|
|
--add-tracker DOMAIN ensure the provided tracker domain is added to each torrent's tracker list
|
|
|
|
-h, --help show this help message and exit
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
update_tracker.py --add-tracker hyperreal.coffee
|
2024-08-06 03:14:16 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
import json
|
|
|
|
import subprocess
|
|
|
|
import tempfile
|
|
|
|
from pathlib import Path
|
|
|
|
|
2024-11-06 00:59:30 +01:00
|
|
|
import qbittorrentapi
|
2024-08-06 03:14:16 +02:00
|
|
|
from docopt import docopt
|
2024-08-11 00:34:03 +02:00
|
|
|
from rich.console import Console
|
|
|
|
from rich.text import Text
|
2024-08-06 03:14:16 +02:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
args = docopt(__doc__) # type: ignore
|
|
|
|
|
2024-10-15 00:07:17 +02:00
|
|
|
tracker_domain = args["--add-tracker"]
|
|
|
|
|
2024-08-11 00:34:03 +02:00
|
|
|
console = Console()
|
|
|
|
with console.status("[bold green]Executing the tasks...") as status:
|
|
|
|
# JSON file containing authentication info for each qBittorrent instance
|
|
|
|
QBITTORRENT_AUTH_FILE = Path.home().joinpath(".config/qbittorrent_auth.json")
|
|
|
|
|
|
|
|
# Open authentication file and load JSON data
|
|
|
|
with open(QBITTORRENT_AUTH_FILE, "r") as qbt_auth:
|
|
|
|
auth_data = json.load(qbt_auth)
|
|
|
|
|
|
|
|
# Collect infohashes of all torrents in each qBittorrent instance
|
|
|
|
console.log(
|
2024-08-11 05:31:41 +02:00
|
|
|
"Collecting infohashes of all torrents in each qBittorrent instance."
|
2024-08-06 03:14:16 +02:00
|
|
|
)
|
2024-08-11 00:34:03 +02:00
|
|
|
torrent_infohashes = []
|
|
|
|
for item in auth_data["instances"]:
|
2024-11-06 00:59:30 +01:00
|
|
|
with qbittorrentapi.Client(
|
|
|
|
host=item["hostname"],
|
|
|
|
username=item["username"],
|
|
|
|
password=item["password"],
|
|
|
|
) as qbt_client:
|
|
|
|
try:
|
|
|
|
qbt_client.auth_log_in()
|
|
|
|
except qbittorrentapi.LoginFailed as e:
|
|
|
|
print(e)
|
|
|
|
|
|
|
|
for torrent in qbt_client.torrents_info():
|
|
|
|
torrent_infohashes.append(torrent.hash)
|
2024-08-11 00:34:03 +02:00
|
|
|
|
|
|
|
# Format the infohashes to have a \n at the end
|
2024-08-11 05:31:41 +02:00
|
|
|
console.log("Formatting infohashes to have a newline at the end.")
|
2024-08-11 00:34:03 +02:00
|
|
|
format_infohashes = set([f"{infohash}\n" for infohash in torrent_infohashes])
|
|
|
|
|
|
|
|
# Create a NamedTemporaryFile and write all infohashes to it, one per line
|
2024-08-11 05:31:41 +02:00
|
|
|
console.log("Creating temporary file to write infohashes to.")
|
2024-08-11 00:34:03 +02:00
|
|
|
with tempfile.NamedTemporaryFile() as ntf:
|
|
|
|
with open(ntf.name, "w") as tf:
|
|
|
|
tf.writelines(format_infohashes)
|
|
|
|
|
|
|
|
# Use scp to copy the infohashes file to the torrent tracker's config
|
|
|
|
# directory on the remote torrent tracker server, overwriting the
|
|
|
|
# whitelist.txt file
|
|
|
|
console.log(
|
2024-08-11 05:31:41 +02:00
|
|
|
"SSH-copying the temporary infohashes file to the torrent tracker's whitelist."
|
2024-08-11 00:34:03 +02:00
|
|
|
)
|
|
|
|
subprocess.run(
|
|
|
|
[
|
|
|
|
"scp",
|
|
|
|
"-q",
|
|
|
|
ntf.name,
|
2024-10-15 00:07:17 +02:00
|
|
|
f"root@{tracker_domain}:/etc/opentracker/whitelist.txt",
|
2024-08-11 00:34:03 +02:00
|
|
|
]
|
|
|
|
)
|
2024-08-06 03:14:16 +02:00
|
|
|
|
2024-08-11 00:34:03 +02:00
|
|
|
# Use SSH to run `systemctl restart opentracker.service` on the remote
|
|
|
|
# torrent tracker server
|
2024-08-11 05:31:41 +02:00
|
|
|
console.log("Restarting opentracker.service on the remote server.")
|
2024-08-11 00:34:03 +02:00
|
|
|
subprocess.run(
|
|
|
|
[
|
|
|
|
"ssh",
|
2024-10-15 00:07:17 +02:00
|
|
|
f"root@{tracker_domain}",
|
2024-08-11 00:34:03 +02:00
|
|
|
"systemctl",
|
|
|
|
"restart",
|
|
|
|
"opentracker.service",
|
|
|
|
]
|
2024-08-06 03:14:16 +02:00
|
|
|
)
|
2024-08-11 00:34:03 +02:00
|
|
|
|
|
|
|
# Reannounce all torrents in each qBittorrent instance to their trackers
|
2024-08-11 05:31:41 +02:00
|
|
|
console.log("Reannouncing all torrents to their trackers.")
|
2024-08-11 00:34:03 +02:00
|
|
|
for item in auth_data["instances"]:
|
2024-11-06 00:59:30 +01:00
|
|
|
with qbittorrentapi.Client(
|
|
|
|
host=item["hostname"],
|
|
|
|
username=item["username"],
|
|
|
|
password=item["password"],
|
|
|
|
) as qbt_client:
|
|
|
|
for torrent in qbt_client.torrents_info():
|
|
|
|
torrent.reannounce(torrent.hash)
|
2024-08-11 00:34:03 +02:00
|
|
|
|
2024-08-11 05:31:41 +02:00
|
|
|
console.log("Done!")
|
|
|
|
|
2024-08-11 00:34:03 +02:00
|
|
|
# Print output and make it look sexy ;)
|
|
|
|
console = Console()
|
2024-08-11 05:31:41 +02:00
|
|
|
tasks = Text("\nTasks completed:\n")
|
2024-08-11 00:34:03 +02:00
|
|
|
tasks.stylize("bold magenta")
|
|
|
|
console.print(tasks)
|
|
|
|
console.print(":white_check_mark: update the tracker's whitelist")
|
|
|
|
|
2024-10-15 00:07:17 +02:00
|
|
|
if tracker_domain:
|
2024-08-11 00:34:03 +02:00
|
|
|
console.print(
|
2024-10-15 00:07:17 +02:00
|
|
|
f":white_check_mark: ensure {tracker_domain}:6969/announce is in each torrent's tracker list"
|
2024-08-11 00:34:03 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
console.print(":white_check_mark: reannounce all torrents to their trackers")
|
|
|
|
|
|
|
|
torrents = Text(str(len(torrent_infohashes)))
|
|
|
|
torrents.stylize("bold green")
|
|
|
|
console.print(torrents + " torrents were updated")
|