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