Assorted shell and Python scripts
at main 4.6 kB view raw
1#!/usr/bin/env -S uv run --script 2# /// script 3# dependencies = [ 4# "qbittorrent-api", 5# "docopt", 6# "rich", 7# ] 8# /// 9 10"""update_tracker.py 11 12Description: 13This script collects infohashes of all torrents in each qBittorrent instance, 14updates opentracker, and reannounces all torrents to their trackers. 15 16Expectations: 17- A JSON qBittorrent authentication file at ~/.config/qbittorrent_auth.json 18- SSH pubkey access to torrent tracker server 19- rsync installed on the host system running this script 20 21Usage: 22 update_tracker.py (--add-tracker DOMAIN) 23 update_tracker.py -h 24 25Options: 26 --add-tracker DOMAIN ensure the provided tracker domain is added to each torrent's tracker list 27 -h, --help show this help message and exit 28 29Examples: 30 update_tracker.py --add-tracker hyperreal.coffee 31""" 32 33import json 34import subprocess 35import tempfile 36from pathlib import Path 37 38import qbittorrentapi 39from docopt import docopt 40from rich.console import Console 41from rich.text import Text 42 43if __name__ == "__main__": 44 args = docopt(__doc__) # type: ignore 45 46 tracker_domain = args["--add-tracker"] 47 48 console = Console() 49 with console.status("[bold green]Executing the tasks...") as status: 50 # JSON file containing authentication info for each qBittorrent instance 51 QBITTORRENT_AUTH_FILE = Path.home().joinpath(".config/qbittorrent_auth.json") 52 53 # Open authentication file and load JSON data 54 with open(QBITTORRENT_AUTH_FILE, "r") as qbt_auth: 55 auth_data = json.load(qbt_auth) 56 57 # Collect infohashes of all torrents in each qBittorrent instance 58 console.log( 59 "Collecting infohashes of all torrents in each qBittorrent instance." 60 ) 61 torrent_infohashes = [] 62 for item in auth_data["instances"]: 63 with qbittorrentapi.Client( 64 host=item["hostname"], 65 username=item["username"], 66 password=item["password"], 67 ) as qbt_client: 68 try: 69 qbt_client.auth_log_in() 70 except qbittorrentapi.LoginFailed as e: 71 print(e) 72 73 for torrent in qbt_client.torrents_info(): 74 torrent_infohashes.append(torrent.hash) 75 76 # Format the infohashes to have a \n at the end 77 console.log("Formatting infohashes to have a newline at the end.") 78 format_infohashes = set([f"{infohash}\n" for infohash in torrent_infohashes]) 79 80 # Create a NamedTemporaryFile and write all infohashes to it, one per line 81 console.log("Creating temporary file to write infohashes to.") 82 83 with tempfile.NamedTemporaryFile() as ntf: 84 with open(ntf.name, "w") as tf: 85 tf.writelines(format_infohashes) 86 87 # Use `sudo cp -f` to copy the infohashes file to the torrent tracker's config 88 # directory, overwriting the whitelist.txt file. 89 console.log( 90 "Copying the temporary infohashes file to the torrent tracker's whitelist." 91 ) 92 subprocess.run( 93 ["sudo", "cp", "-f", ntf.name, "/etc/opentracker/whitelist.txt"] 94 ) 95 96 # Run `sudo systemctl restart opentracker.service` 97 console.log("Restarting opentracker.service") 98 subprocess.run(["sudo", "systemctl", "restart", "opentracker.service"]) 99 100 # Reannounce all torrents in each qBittorrent instance to their trackers 101 console.log("Reannouncing all torrents to their trackers.") 102 for item in auth_data["instances"]: 103 with qbittorrentapi.Client( 104 host=item["hostname"], 105 username=item["username"], 106 password=item["password"], 107 ) as qbt_client: 108 for torrent in qbt_client.torrents_info(): 109 torrent.reannounce() 110 111 console.log("Done!") 112 113 # Print output and make it look sexy ;) 114 console = Console() 115 tasks = Text("\nTasks completed:\n") 116 tasks.stylize("bold magenta") 117 console.print(tasks) 118 console.print(":white_check_mark: update the tracker's whitelist") 119 120 if tracker_domain: 121 console.print( 122 f":white_check_mark: ensure {tracker_domain}:6969/announce is in each torrent's tracker list" 123 ) 124 125 console.print(":white_check_mark: reannounce all torrents to their trackers") 126 127 torrents = Text(str(len(torrent_infohashes))) 128 torrents.stylize("bold green") 129 console.print(torrents + " torrents were updated")